Deploying the Blog

- 9 mins read

Hugo gets promoted

I was planning to only use Hugo for the blog portion of my site and spend more time building the core site with something like Alpine.js or whatever the new hot frontend tool is. However, I don’t really have any core content to show at this point other than links to a couple of demo projects when I was learning ClojureScript and Three.js years ago. I figure I might as well use Hugo for the root site and build out from there. The theme templates seem easy enough to customize and extend if I want to put more effort into the site in the future. My current goal is to just get something up and running that looks decent enough so I can switch my focus back to my game project. Hugo seems like the perfect tool to achieve that goal in a short amount of time. Let’s drop it in as a replacement for my root content.

Next steps

  • Build initial static files for empty site and copy to my server
  • Push local Hugo site project to a GitHub repo
  • Copy my first journal entries to markdown template pages to render as posts
  • Create an automated deploy process to get site changes synced on the server (not a priority but I enjoy this kind of work)

Wait, that’s illegal!

If I’m going to put the Hugo artifacts into a public GitHub repo, I should be aware of any licensing concerns with the software I’m adding there. Having a public repo which anyone can clone is considered distribution of the contents of that repo. Even though I don’t intend for my personal site content to be distributed as open source software, I still need to be aware of third party source code I’m including.

Since I’m using Hugo to generate artifacts but not including the tool’s source code in my repo, the Apache 2.0 license for that software doesn’t really come into play. The Poison theme, however, is included in my repo as a git submodule which is a bit fuzzy in terms of whether the source code is included in the distribution of the code someone may download from my public repo. I’m going to play it safe and just license my project under the same GNU General Public License v3.0 under which Poison is also licensed.

Git happens

I already initialized my local git repository as part of the Hugo quick start setup which instructed to use the example theme as a git submodule. Even though I don’t have any journal content at this point (I’m still writing this entry in OneNote), I want to get a “walking skeleton” deployed as early as possible and establish a workflow to iterate on the project. I commit the base code for the empty site generated by Hugo to my local repo and head over to GitHub.com to create my remote repository and push up my code.

Deploying the skeleton

I run the build command for Hugo to generate the artifacts for the static site content with hugo --gc --minify

I plan to use rsync to synchronize the generated content in my local public/ directory with my server. I already have ssh configured for this server so I shouldn’t’ need to do much to get this working. I run the rsync command from my local WSL terminal to a test directory on my Digital Ocean dev server, but run into an error which I quickly find out means I didn’t have rsync installed on the server. After installing the tool, I run rsync with the dry-run switch (-n) and no errors this time.

rsync -avzn --delete public/ do-dev:~/test-hugo

Now, I run the actual command without dry-run and point to a subdirectory within my existing static content root. Even though I’ll be using the Hugo site content for my root site, I want to do the initial deploy to a subdirectory in case I need to revert. Since I already configured Nginx to serve static content, I don’t need to modify any configuration to serve the new Hugo content. I open up my browser and head to corkbits.com/blog, but something isn’t right: Something went wrong

Shaving Yaks

The theme isn’t loading which should be coming from the bundled .js and .css asset files. To see if this is an issue with the server or the content itself, I want to run an http server from my local machine.

I usually reach for http-server via NPM for this type of quick troubleshooting, however, I have only been working within Dev Containers in my WSL environment since I built this PC last November and haven’t needed to install Node.

I get the required tools installed in a couple of quick commands:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install 22 npm install -g http-server

I then remember that I do have asdf installed which I could have used instead of installing a version manager specific to Node. Oh well. I’m already off course here so I don’t sweat it.

Let’s spin up the local web server to serve the generated content:

cd ~/blogsite/public http-server -p 8000

The result is the same. The network tab in Chrome Dev Tools shows the .js and .css files aren’t found by the server. I realize what I should have seen before going on the local server side quest is to check the URL from which the site was trying to download assets. It’s more obvious when running locally as the asset file is trying to download from https://corkbits.com/css/bundle.min.<file_hash>.css which is clearly not where the asset file exists. The references to the asset files in index.html are generated from the baseUrl parameter in the hugo.toml file which is set to https://corkbits.com.

I confirm that the content exists where it should on the server by copying the URL to the CSS file and manually changing the prefix to https://corkbits.com/blog. The content downloads successfully and confirms that the problem was simply configuration.

Since the base HTML file for the site is loading correctly and the assets should work once their file locations match the configured baseUrl, I go ahead and make the Hugo site my root content. After backing up the existing root content (there isn’t much) to another directory, I move the contents of the blog/ up a level to the root of my static directory. I check the site in a browser at corkbits.com and the theme is now loading!

Is it time to automate the deployment?

No. Not fully at least.

I create a simple script in my home directory to build and push the content for whenever I have updates.

#!/bin/bash cd blogsite hugo --gc --minify rsync -avz --delete public/ do-dev:/var/www/corkbits.com/html

It wouldn’t take much to stick these simple commands into GitHub Actions and set a trigger to run everytime there is a commit to the main branch. However, I am ready to start putting my journal entries as content for the site and don’t want to fiddle with another tool right now. Once I get to a point where it’s painful enough to not have the triggered deploy, I’ll put in the effort. For now, this script works well enough for my needs.

I add some small changes to include social links for GitHub, LinkedIn, and email, then run the deploy script. The change is replicated on the live site in the browser moments later!

And now, back to our regularly scheduled programming

It’s time to create the first blog post entry. I already have yesterday’s entry written in OneNote. I’ll just have to copy the content to a markdown template file. I run the Hugo generator command hugo new content journal/20240603.md which spits out a new file at the expected directory within content/. I add some placholder text and save, but the entry does not automatically show on the main site page as I previously saw in the quick start process when I ran hugo new content posts/my-first-post.md.

I dig into the file themes/poison/layouts/index.html and see the line

{{ $frontPageTypes := default (slice "posts") .Site.Params.front_page_content }

I take this clue to the Poison docs and search for the term front_page_content. Sure enough, there is a section “The front page” which tells me exactly what I need to do to get my journal entries showing up like the default “posts” entries do. I make the change to hugo.toml and a link to my placeholder entry is now rendering on the front page.

[parms] ... front_page_content = ["journal"]

I commit the configuration change then copy my OneNote entry from yesterday to replace the placeholder content. I run the deploy script and I have officially posted my first public journal entry!

Customizing the theme

The last thing I want to do today is remove the copyright footer in the sidebar. I’m pretty sure people only put these copyright notes on websites because that’s just what everyone has always done, but its presence doesn’t really do anything meaningful in the year 2024.

This copyright line is hardcoded in the theme template file which I can modify on my local copy, but since I’m using the theme source as a git submodule, the changes can’t be persisted in my repo. This means if I ever run a deploy from another machine, the original template will be used. Does this mean I should clone the code in my repo instead of using as a submodule? With this option, I would lose the benefit of easily pulling in theme updates from the source so maybe I don’t want to go down this path.

It looks like the better option is to override the theme template which is a built-in feature of Hugo.

I copy the original template from themes/poison/layouts/partials/sidebar/sidebar.html to layouts/partials/sidebar/sidebar.html. I then comment out the reference to the copyright partial I don’t want to include on my site.

<aside class="sidebar"> <div class="container sidebar-sticky"> {{ partial "light_dark.html" . }} {{ partial "sidebar/title.html" . }} {{ partial "sidebar/menu.html" . }} {{ partial "sidebar/socials.html" . }} <!-- {{ partial "sidebar/copyright.html" . }} --> </div> </aside>

Now that I’m comfortable with these new tools and I’ve established a process for releasing content to the wild, I’m ready to switch my focus back to the project I really want to write about, my turn-based dungeon crawl game!