Switching From Wordpress To Hugo
It’s Been a Long Way⌗
It feels like I’ve been posting these kinds of website update posts every few months (or years). I still remember the day I got the first version of my website working in middle school. It’s been about 6 years since that day (wow). And the domain DeemOcean.com has been in use for 5 years. One good thing about keeping a website alive for so long and actively maintaining its SEO is achieving a high rank in search engines, even with my lazy update rate of more than a month.
So I tried putting Google Ads on the website to see how much passive income I can get:It is really not bad, was peaked at $200 per month even with 0 posts for a long time.
Why the Switch⌗
Wordpress is really not bad for a new website builder with almost zero experience. But it’s the kind of thing you’ll enjoy if your use cases are just within its design range. The moment you want something specific, it just gets annoying to use. And I don’t even need most of the functionalities in its package. This results in a messy, slow website that is hard to customize.
Also, it has security risks. Two months ago, my website got hacked and there were like 200 pages of Casino Ads. Part of that is my problem, since I basically never visited the website to check for too long.
But, I always wanted something more elegant, with nice version control features, and fast. Thus, I made the decision to switch to the Hugo Framework.
The Setup⌗
I am a huge fan of CloudFlare and have been using it for 5 years - I absolutely love it. It has a feature called Pages, which is somewhat similar to GitHub Pages, but with the CloudFlare network. Since it’s free, I’m also saving on server fees. (For anyone who wants to do the same, it provides a free X.pages.dev domain.)
In this way, I created a private GitHub repo for my website, and every time I push to the repo, CloudFlare automatically builds my website and then publishes it onto its global networks.
Modifications⌗
Hugo gives you so much freedom to do things, so I have added many features to it.
A Hugo Shortcodes is a simple snippet inside a content file that Hugo will render using a predefined template.
One of these is the figure
shortcode for inserting images with my desired functionalities:
<figure {{ with .Get "pos" }}class="{{.}}"{{ end }}>
{{- if .Get "link" -}}
<a href="{{ .Get "link" }}" {{ with .Get "target" }} target="{{ . }}" {{ end }}{{ with .Get "rel" }} rel="{{ . }}" {{ end }}>
{{- end }}
<img src="{{ .Get "src" }}"
class="{{ .Get "pos" }}"
{{- if or (.Get "alt" ) (.Get "caption" ) }}
alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "caption" | markdownify| plainify }}{{ end }}"
{{- end -}}
{{- with .Get "width" }} width="{{ . }}"{{ end -}}
{{- with .Get "height" }} height="{{ . }}"{{ end -}}
style="{{- with .Get "style" }} {{ . | safeCSS }};{{ end -}}
{{- with .Get "round" }}border-radius: {{ . | safeCSS }}px;{{ end -}}
{{- with .Get "rotate" }}transform: rotate({{ . | safeCSS }}deg);{{ end }}"
/>
</figure>
Which gives the options like link
pos
src
alt
caption
width
height
style
round
rotate
Image Optimization⌗
I have a lot of images on this website, to have a good performance, I wrote a python script to backup the original files into a folder with the same relative paths,
and replace the images with a optimizaed .webp
file without metadata.
# THIS FILE ASSUMES PROJ ROOT DIR
import os
import re
import shutil
from PIL import Image, ImageSequence
from tqdm import tqdm
# the folders to be optimized
path = ['static/','content/DeemoGraphy/']
# backup the files to a new folder
orig_path = ['ORIG/static_ORIG/', 'ORIG/gallery_ORIG/']
for i in range(len(path)):
# Get the list of files and folders in the source directory tree
source_items = list(os.walk(path[i]))
# all common imgs
img_pattern = re.compile(r'\.(jpg|png|jpeg)$', re.IGNORECASE)
gif_pattern = re.compile(r'\.gif$', re.IGNORECASE)
# optimize
progress_bar = tqdm(source_items, desc="Optimizing", unit="file")
for rootDir, subdirs, filenames in progress_bar:
# Create the corresponding directories in the destination folder
for dir_name in subdirs:
source_dir_path = os.path.join(rootDir, dir_name)
destination_dir_path = source_dir_path.replace(path[i], orig_path[i], 1)
os.makedirs(destination_dir_path, exist_ok=True)
for filename in filenames:
file_path = os.path.join(rootDir, filename)
bkup_file_path = file_path.replace(path[i], orig_path[i], 1)
try:
if img_pattern.search(filename):
#BACK UP
shutil.copy(file_path, bkup_file_path)
progress_bar.write(f"Backing up: {file_path}")
#########
img = Image.open(file_path)
#REMOVE metadata
img.info.pop('exif', None)
progress_bar.write(f"Removing EXIF(METADATA): {file_path}")
#OPTIMIZATION
img.save(os.path.splitext(file_path)[0]+'.webp', optimize=True, quality=85,format="webp")
os.remove(file_path)
progress_bar.write(f"Optimizting: {file_path}")
except OSError:
print("Error while saving file")
print("Back-Up & EXIF(METADATA) Removal & Optimization DONE")
Shell Shortcuts⌗
Obviously I need a quick way to maintain all my custom functionalities, so I wrote a shell .alias
script to
take over the boring part of using the terminal:
WORKSPACE_PATH=$HOME/Desktop/workspace
BLOG_PATH=$WORKSPACE_PATH/DeemOcean
# Use double quotes around variables and remove spaces around the equal sign
alias gowk="cd $WORKSPACE_PATH"
alias goblog="cd $BLOG_PATH"
function blog() {
goblog
case $1 in
"new")
hugo new posts/$2.md
;;
"server")
hugo server --noHTTPCache;;
"opt")
python opt.py;;
"commit")
echo "------------------------"
echo "committing custom theme..."
cd themes/terminal
git add .
git commit -m $2
cd ../..
echo "------------------------"
echo "committing blog..."
git add .
git commit -m $2;;
"push")
echo "------------------------"
echo "pushing custom theme..."
cd themes/terminal
git push
echo "------------------------"
echo "pushing blog..."
cd ../..
git push;;
"")
echo "landing at blog dir";;
*)
echo "invalid blog option";;
esac
}
Domains⌗
You might noticed that the main domain for this website now is dmo.page
, but I have added the URL page redirect rules.
Meaning the old DeemOcean.com/somesection/somepage
indexed by Search Engines will be redirect to dmo.page/somesection/somepage
It is a painless transition :D