Or: ‘How I Learned to Stop Worrying and Love the Code’

There are whole buch of ‘How To’ blogs on the Interwebs about moving from WordPress to a Static Site Generator (SSG).

This is not another one of those, it’s more my Notes and Thoughts.

First, Why NOT?

I’m not really interested in the recent WordPress shenanigans.

As a self-hoster, one petty millionaire being cross at another millionaire doesn’t affect me in the slightest.

This is not the reason that I made the move.

So, Why?

There are a number of reasons why.

This site only really existed as a vehicle for me the learn about WorldPress, and I feel as if I’ve come to the end of that journey.

I’d also noticed something else, my writing had become SEO oriented; I was becoming transfixed on getting all the Yeost SEO green dots for each post.

I was losing my writing style to please the Google Gods and I didn’t like that.

I wanted to learn something new.

I’m very much of the midset “everything is working now; time to change it”.

There is a longer term plan to offload my static sites onto my old SheevaPlug which currently resides in the ‘Cupboard of Forgotten Tech’ , so this is the first step on that journey.

Static sites are blazingly fast.

Exporting WordPress Content

I tried both:

The first requires downloading, unzipping and adding to the /wp-content/plugins/ folder.

The second can either be installed as a plugin; or downloaded, unzipped and placed in the /wp-content/plugins/ folder.

More tools can be found here .

For my usage the Jekyll exporter worked better.

Creating Markdown Content

By far the biggest time sink was cleaning up the export.

Yes, both of the above produced usable Markdown.

Yet:

  • WordPress html artifacts remained
  • Images were in a weird folder
  • Images had lost their alt text
  • Generally it was all a bit of a mess

All of the above and a bunch of other things I can’t remember needed addressing before I was happy with the Markdown.

It was essentially a long find and replace few hours.

The process did however afforded me the opportunity to do a bit of light editing (read: get rid of some of the SEO chasing I’d done in the past).

Stuff I Don’t Like

There is one thing that I don’t really like about static sites, and that’s where the content ends up in relation to the final URL.

In the development enviroment all of the content goes under /content/posts/.

This, I like; it’s tidy and uncluttered.

However, when deploying to the web server this hierarchy is replicated, meaning that my content ends up in https://tld/posts/my-post.html.

This, I don’t like.

I completely understand why this happens.

I completely understand how having a database prevents this happening.

I also understand that I can take out the /posts/ portion of the URL by editing the [permalinks] in the hugo.yaml config file.

Unfortunately that leads to everything being in the server’s root folder; which is untidy and cluttered.

I should probably look at creating an nginx rewrite rule or something.

An Inelegant nginx Rewrite Rule

So, I cobbled together the below, while I look for a one line regex rewrite rule:

# 0001
location /googleaiy-raspberrypi-scroll-phat/ {
    rewrite ^/googleaiy-raspberrypi-scroll-phat/ /posts/2018/04/googleaiy-raspberrypi-scroll-phat/ break;
}

# 0002
location /refurbishing-a-picade/ {
    rewrite ^/refurbishing-a-picade/ /posts/2018/10/refurbishing-a-picade/ break;
}

My Current Workflow

The Internet told me that a good chunk of time would be sunk into developing the new way of working.

Yep, this turned out to be true.

Not least of all:

  • Getting content to the web server with the correct permissions
  • Backing up the current content

So, naturally I wrote a bash script that does the following:

  • Stop the Hugo dev-server
  • chown the remote web server directory (take ownership)
  • Remove any existing content on the remote web server
  • Remove any existing local Hugo ‘/public’ content
  • Build the new local Hugo website
  • Copy the Hugo ‘/public’ content to the remote web server
  • chown the remote web server directory (give ownership to www-data)
  • Backup (rsync) the working directory
  • Clear out the Hugo generated ‘/public’ folder before syncing (no need to store this in Forgejo)
  • Push ‘/path/to/git/hugo/’ to Forgejo
  • Start the Hugo dev-server

The Deployment Script

deploy.sh

This is linked to an alias in my .bashrc file so that I can simply type ‘Deploy_CT_Current’ in a Termininal, and it goes off and does its thing.

In a Terminal:

nano .bashrc

Add:

# Add deploy alias(s) for Hugo
alias deploy="bash /path/to/script/deploy.sh"

Then reload .bashrc.

source ~/.bashrc

Feel free to chop this up and season to taste:

#!/bin/bash

# Functions
nuke_hugo () {
    clear;
    echo "";
    # Nuke the existing Hugo installation
    echo -e "\e[1;36mNuke the existing Hugo installation...\e[0m";
    # Sleep so the screen can be read before moving on
    sleep 2;

    # Stop the Hugo dev-server
    echo "";
    echo -e "\e[1;33mStop the Hugo dev-server...\e[0m";
    killall hugo;
    echo -e "\e[32mDone\e[0m";
    echo "";

    # chown the remote web server directory (take ownership)
    echo -e "\e[1;33mchown the remote web server directory (take ownership)...\e[0m";
    ssh -t foo@server 'sudo chown $USER:$USER -R /var/www/example.org';
    echo -e "\e[32mDone\e[0m";
    echo "";

    # Remove any existing content on the remote web server
    echo -e "\e[1;33mRemove any existing content on the remote web server...\e[0m";
    ssh -t foo@server 'rm -R /var/www/example.org/*';
    echo -e "\e[32mDone\e[0m";
    echo "";

    # Remove any existing local Hugo '/public' content
    echo -e "\e[1;33mRemove any existing local Hugo '/public' content...\e[0m";
    rm -R /path/to/local/hugo/public/*;
    echo -e "\e[32mDone\e[0m";
    echo "";

    # Build the new local Hugo website
    echo -e "\e[1;33mBuild the new local Hugo website...\e[0m";
    (cd /path/to/local/hugo/ && hugo);
    echo -e "\e[32mDone\e[0m";
    echo "";

    # Copy the Hugo '/public' content to the remote web server
    echo -e "\e[1;33mCopy the Hugo '/public' content to the remote web server...\e[0m";
    scp -r /path/to/local/hugo/public/* foo@server:/var/www/example.org/;
    echo -e "\e[32mDone\e[0m";
    echo "";

    # chown the remote web server directory (give ownership to www-data)
    echo -e "\e[1;33mchown the remote web server directory (give ownership to www-data)...\e[0m";
    ssh -t foo@server 'sudo chown www-data:www-data -R /var/www/example.org';
    echo -e "\e[32mDone\e[0m";
    echo "";

    # Backup (rsync) the working directory
    echo "";
    echo -e "\e[1;33mBackup (rsync) the working directory...\e[0m";
    rsync -a -P --delete -v --exclude '.git' /path/to/local/hugo /path/to/git/hugo;
    echo -e "\e[32mDone\e[0m";
    echo "";

    # Clear out the Hugo generated '/public' folder before syncing (no need to store this in Forgejo)
    echo -e "\e[1;33mClear out the Hugo generated '/public' folder before syncing (no need to store this in Forgejo)...\e[0m";
    rm -R /path/to/git/hugo/public/*;
    echo -e "\e[32mDone\e[0m";
    echo "";

    # Push '/path/to/git/hugo/' to Forgejo
    echo -e "\e[1;33mPush '/path/to/git/hugo/' to Forgejo...\e[0m";
    cd /path/to/git/hugo/;
    git add .;
    git commit -m 'Modified' .;
    git push -u origin main;
    echo -e "\e[32mDone\e[0m";
    echo "";

    # Start the Hugo dev-server
    echo -e "\e[1;33mStart the hugo dev-server...\e[0m";
    hugo server -s /path/to/local/hugo;
    echo -e "\e[32mDone\e[0m";
    echo "";
}

# Start by clearing the Terminal window
clear

echo "";
echo -e "\e[1;34mUse \e[1;36mCtrl-c\e[1;34m to \e[1;31mExit\e[1;34m and close the window...\e[0m";
echo "";
echo -e "\e[1;31mNuke\e[1;34m will:";
echo -e "     Stop the Hugo dev-server";
echo -e "     chown the remote web server directory (take ownership)";
echo -e "     Remove any existing content on the remote web server";
echo -e "     Remove any existing local Hugo '/public' content";
echo -e "     Build the new local Hugo website";
echo -e "     Copy the Hugo '/public' content to the remote web server";
echo -e "     chown the remote web server directory (give ownership to www-data)";
echo -e "     Backup (rsync) the working directory";
echo -e "     Clear out the Hugo generated '/public' folder before syncing (no need to store this in Forgejo)";
echo -e "     Push '/path/to/git/hugo/' to Forgejo";
echo -e "     Start the Hugo dev-server";
echo "";

# Loop
while true; do
    options=("Nuke")

    echo -e "\e[1;36mChoose an option:\e[0m"
    select opt in "${options[@]}"; do
        case $REPLY in
            1) nuke_hugo; break ;;
            *) echo "Whoops, choose again, option '$REPLY' is invalid..." >&2
        esac
    done

done

Hope that helps someone.