Posts tagged with "Hugo"

from GitHub to Codeberg

I migrated this blog to GitHub and Netlify back in September 2022. Three years later, I decided to move my (small) number of GitHub repositories to Codeberg as I was impressed by their approach to open source software, transparent communications and I always like to support the underdog.

I'm not a developer and my GitHub repositories were mainly historical versions of my blog over the years placed under version control and as a backup.

My GitHub repos were all basic; single user and didn't include any issues, pull requests and hardly any branches. Consequently, I simply followed the Codeberg documentation and the transition was quick and seamless, preserving all the commit history.

As the test migration went smoothly, I then considered simplifying my blog workflow by removing the dependency on GitHub pages and Netlify. Six months ago, Codeberg provided Codeberg pages which looked to be very similar to GitHub pages.

The blog publishing process previously performed by Netlify's integration with GitHub pages would now be implemented using Codeberg's Woodpecker Continuous Integration (CI) and Codeberg pages.

You had to apply for privileges to use Woodpecker but my request was approved very promptly.

Codeberg helpfully provided examples of Woodpecker files for popular tasks which included a YAML template to publish a Hugo blog from a Codeberg repository to Codeberg pages.

Once I had configured my Codeberg secrets for the Codeberg token and email address and a few iterations, it was working !

Code CI Blog Publish

I liked the Codeberg CI dashboard summary with traffic light icons indicating the success (failure) of each stage together with timing information and the ability to get detailed log information for each stage of the process.

The Codeberg publish process has three stages:

git

The initial 'git' stage fetches the latest changes from the Codeberg repository.

+ git init --object-format sha1 -b main
Initialized empty Git repository in /woodpecker/src/codeberg.org/andyc/yakshaving/.git/
+ git config --global --replace-all safe.directory /woodpecker/src/codeberg.org/andyc/yakshaving
+ git remote add origin https://codeberg.org/andyc/yakshaving.git
+ git fetch --no-tags --depth=1 --filter=tree:0 origin +ed01403b33c60e32ae05f6c81e07fe432ed6100a:
From https://codeberg.org/andyc/yakshaving
 * branch            ed01403b33c60e32ae05f6c81e07fe432ed6100a -> FETCH_HEAD
+ git reset --hard -q ed01403b33c60e32ae05f6c81e07fe432ed6100a
+ git submodule update --init --recursive --depth=1 --recommend-shallow
+ git lfs fetch
Fetching reference refs/heads/main
+ git lfs checkout

build

The 'build' stage builds the site using Hugo and includes the version of Hugo used by Codeberg (useful for debugging issues) and timing information.

+ hugo --minify
Start building sites …
hugo v0.154.5-a6f99+extended linux/amd64 BuildDate=2026-01-11T20:53:23Z
                  |  EN
------------------|-------
 Pages            | 1156
 Paginator pages  |  297
 Non-page files   |    0
 Static files     |  132
 Processed images |    0
 Aliases          |   61
 Cleaned          |    0
 Total in 2612 ms

publish

The 'publish' phase deploys the generated site to Codeberg pages into the 'pages' branch.

+ git config --global user.email $MAIL
+ git config --global user.name "Woodpecker CI"
+ git clone -b pages https://$CODEBERG_TOKEN@codeberg.org/$CI_REPO.git $CI_REPO_NAME
Cloning into 'yakshaving'...
+ cp -ar $HUGO_OUTPUT/. $CI_REPO_NAME/
+ cp .domains $CI_REPO_NAME || true
+ cd $CI_REPO_NAME
+ git add .
+ git commit -m "Woodpecker CI ed01403b33c60e32ae05f6c81e07fe432ed6100a"
[pages 292c34d1] Woodpecker CI ed01403b33c60e32ae05f6c81e07fe432ed6100a
 1388 files changed, 6483 insertions(+), 6483 deletions(-)
+ git push
remote:
remote: Create a new pull request for 'pages':
remote:   https://codeberg.org/andyc/yakshaving/compare/main...pages
remote:
To https://codeberg.org/andyc/yakshaving.git
   7c95fab3..292c34d1  pages -> pages

The final stage was to redirect my domain name from Namecheap to the Codeberg URL. Although, I was aware that the answer is always 'DNS', this configuration change was explained clearly in the Codeberg documentation and worked fine.

reflections on Hugo, GitHub and Netlify

Three years ago I moved my Hugo blog to GitHub Pages and Netlify.

When this end to end process worked successfully, this was brilliant. However, at times, the automated deployment did feel like the game of Mousetrap where a silver ball was released and then proceeded to traverse helter skelters, ride up and down on see-saws, descend zig-zag staircases, cross bridges, trigger catapults, release levers and conquer various hazards before finally launching a bucket to capture a little plastic mouse.

By using GitHub pages and Netlify, I had introduced yet more complexity into the blog publishing process.

Then I decided to add yet another layer of complexity by composing posts in Emacs using Org Mode and using ox-hugo to convert posts to Markdown format.

For the most part, this worked fine which was satisfying and I congratulated myself on my technical wizardry.

However, Hugo occasionally broke after yet another update. Locating and resolving the root cause of these errors was problematic (for me) as the Hugo release notes are very technical and IMHO primarily aimed at Go and/or theme developers. There is hardly ever any section describing breaking (i.e. non backwards compatible) changes or user visible changes.

A random example from the most recent Hugo release (v0.159.0)

This release greatly improves and simplifies management of Node.js/npm dependencies in a multi-module setup.
Replace deprecated site.Data with hugo.Data in tests.
Replace deprecated excludeFiles and includeFiles with files in tests.
Replace deprecated :filename with :contentbasename in the permalinks test.

Failure could be caused by a variety of multiple potential issues.

  1. Was there an error generating the Markdown from the Org Mode source ?
  2. Did Hugo work locally and generate the HTML for the site successfully ? This was normally the most frequent reason for the failure. An Arch update would often update the Hugo package and Hugo updates were quite frequent.
  3. Did the PaperMod theme need updating to reflect the most recent changes in Hugo ?
  4. Do other popular Hugo themes (Ananke) function without any issues ?
  5. Assuming the local Hugo site works, did the push to GitHub work ? Check the recent updates to the GitHub repository.
  6. Did Netlify then get triggered correctly by the GitHub updates?
  7. Did the Hugo build process complete successfully on Netlify ? What version of Hugo is Netlify using ? Is this identical (or compatible) with the locally installed version of Hugo ?

After yet another issue following a Hugo upgrade, I got increasingly frustrated with this frictionless blogging process that was anything but. I was now spending more time fixing my static (sic), unchanged blog instead of writing any new posts.

Once again, I started to consider using an alternative static site generator. After all, I already had migrated my content to each of the popular SSG's I evaluated last year.

My mind was made up. I was going to do it. Just a question of selecting an SSG and actually doing it.

And then Dave Pearson came along and spoiled everything by creating BlogMore...

fun with static site generators

Introduction

Static site generators (SSG's) are often used for blogs. SSG's typically process Markdown files into static HTML files. The use of static HTML files (rather than dynamically generating the site using a database) offers benefits for performance and security.

I use Hugo for my blog and have used (or experimented with) the following static site generators (SSG's).

  • Hugo (Go)
  • Eleventy (Javascript)
  • BSSG (Bash)
  • Zola (Rust)
  • Nikola (Python)
  • Pelican (Python)
  • Jekyll (Ruby)

A throwaway post from Neil Brown on Mastodon prompted me to investigate the build performance of different static site generators with a significant volume of posts (1,000).

Neil reduced the build time for his Hugo blog simply by adding more hardware resources. A decent strategy involving minimal effort producing an immediate improvement.

'I have upped the RAM in the VM running my Web server to a heady 1GB, and added a second CPU core'.

'That has halved the Hugo build time for my blog [from 4 minutes to 2 minutes]'.

This comment surprised me as I also use Hugo which builds my entire blog, containing 1,000 pages, in less than two seconds on a 10 year old desktop computer.

Neil's blog is self-hosted and uses Hugo. A 'View Source' reveals the version of Hugo in use. Neil is using v0.131.0 (released in August 2024).

<meta name="generator" content="Hugo 0.131.0">

The latest version of Hugo is 0.151.1 (released in October 2025). However, Neil is using the Hugo version included in the Debian (Trixie) repositories.

Reviewing the 'Archives' page, Neil's blog contains 457 posts.

Neil moved his blog from HTMLy to Hugo in 2023 and was using Hugo v.0.111.3 (from the Debian repos) back then and used the Etch theme.

Looking at the Etch theme, it is clear Neil has stuck with this attractive, minimal Hugo theme since then.

Given the disparity between Neil's build time and mine, I thought it would be fun to compare the performance of Hugo with different themes as well as other popular static site generators.

Test Environment

Hardware

  • Lenovo M900 Tower Desktop (SFF)
  • CPU: Intel i7-6700 CPU @ 3.40GHz (4 cores, 8 threads)
  • Memory: 48GB
  • Disk: 1TB
  • O/S: Linux 6.17.2

Test Data

I used my personal blog as the data set for the performance tests.

  • 1028 articles (Markdown)
  • Content spanning twenty years (2005 to 2025)
  • 116 code blocks
  • 74 static images
  • 29 categories
  • 46 tags

Hugo

Hugo: https://gohugo.io/

Hugo is a popular static site generator written in Go with a reputation for speed and performance.

$ hugo version
hugo v0.151.1+extended+withdeploy linux/amd64 BuildDate=unknown
$ go version
go version go1.25.3 X:nodwarf5 linux/amd64

The tests ran the standard hugo build command three times and took the average elapsed time.

ThemeTime (secs)
Ananke0.615
PaperMod (Base)1.067
PaperMod (Custom)1.633
Etch (Base)1.911
Etch (Related)1.958
BearBlog0.425
Simple0.377
Beautiful Hugo1.541

Most Hugo themes used the default, out of the box settings with no customisation.

The 'PaperMod (Custom)' test used my personal blog which includes additional 'Archive', 'Categories', 'Posts' pages and search functionality.

The timings for 'Etch' surprised me as it is a relatively simple theme that displays a list of all posts.

I added support for up to 15 'Related Posts' using Neil's code but saw no noticeable increase in build time (which is less than two seconds).

Hugo supports 'Related Posts' functionality and the list of articles is built during the build (regardless of whether it is used or not).

Ananke: https://github.com/theNewDynamic/gohugo-theme-ananke

PaperMod: https://github.com/adityatelange/hugo-PaperMod

Etch: https://github.com/LukasJoswiak/etch

BearBlog: https://github.com/janraasch/hugo-bearblog

Simple: https://github.com/maolonglong/hugo-simple/

Beautiful Hugo: https://github.com/halogenica/beautifulhugo

Hugo provides useful diagnostics about potential performance bottlenecks.

Here is the template metrics report for the Etch theme (with related posts). There are three candidate templates that could be cached (header, footer and posts).

$ hugo --templateMetrics --templateMetricsHints
Template Metrics:
     cumulative       average       maximum      cache  percent  cached  total
       duration      duration      duration  potential   cached   count  count  template
     ----------      --------      --------  ---------  -------  ------  -----  --------
   2.691672237s   53.833444ms   83.570806ms          0        0       0     50  rss.xml
   1.409607939s    1.345045ms   11.568865ms          0        0       0   1048  single.html
   322.542988ms      307.77µs    2.927895ms         28        0       0   1048  _partials/related.html
   126.863653ms      115.54µs    1.183336ms         44        0       0   1098  _partials/head.html
    81.827628ms   40.913814ms   41.042982ms        100        0       0      2  _partials/posts.html
    79.788949ms      25.193µs     363.218µs          0        0       0   3167  li.html
    55.705094ms    1.160522ms    7.457174ms          0        0       0     48  _default/taxonomy.html
    44.028022ms   44.028022ms   44.028022ms          0        0       0      1  index.html
    43.649693ms   43.649693ms   43.649693ms          0        0       0      1  list.html
    32.992786ms   32.992786ms   32.992786ms          0        0       0      1  sitemap.xml
     24.19536ms      22.035µs     948.957µs        100        0       0   1098  _partials/header.html
     7.410874ms       6.749µs     143.528µs        100        0       0   1098  _partials/footer.html
      961.219µs     106.802µs     278.188µs          0        0       0      9  _shortcodes/figure.html
      708.877µs     141.775µs     299.575µs          0        0       0      5  _markup/render-table.html.html
      551.337µs     110.267µs     208.377µs          0        0       0      5  _markup/render-table.rss.xml
      105.423µs      52.711µs      88.545µs          0        0       0      2  alias.html
       15.147µs      15.147µs      15.147µs          0        0       0      1  /css/dark.css
         1.76µs        1.76µs        1.76µs          0        0       0      1  404.html

Total in 2002 ms

Eleventy

Eleventy: https://www.11ty.dev/

Eleventy is a popular SSG written in Javascript.

Eleventy Base Blog (v9): https://github.com/11ty/eleventy-base-blog

The Eleventy Base Blog theme is minimal and not dissimilar in appearance from the Hugo PaperMod theme.

$ node --version
v20.19.5
$ npx @11ty/eleventy --version
3.1.2

Building the Eleventy blog. Eleventy doesn't have separate 'build' and 'serve' commands.

The Eleventy build summary for my blog.

$ npx @11ty/eleventy --serve
[11ty/eleventy-img] 143 images optimized (143 deferred)
[11ty] Benchmark   1664ms  11%  1052× (Configuration) "@11ty/eleventy/html-transformer" Transform
[11ty] Copied 5 Wrote 1043 files in 14.53 seconds (13.9ms each, v3.1.2)
[11ty] Server at http://localhost:8080/

Eleventy supports incremental builds using the --incremental parameter which only processes content modified since the last build.

Initially, I saw no difference using --incremental but the Eleventy documentation suggested adding the --ignore-initial option. This reduced the build time significantly from 14 seconds to sub-second.

$ npx @11ty/eleventy --serve --incremental --ignore-initial
[11ty] Copied 5 Wrote 0 files in 0.77 seconds (v3.1.2)
[11ty] Watching…
# Add a new post with tags
[11ty/eleventy-img] 3 images optimized (3 deferred)
[11ty] Wrote 32 files (skipped 1012) in 0.51 seconds (v3.1.2)
# Add more text to existing post
[11ty/eleventy-img] 3 images optimized (3 deferred)
[11ty] Wrote 32 files (skipped 1012) in 0.46 seconds (v3.1.2)

Summary of timings for Eleventy

ThemeTime (secs)
Eleventy (Full)14.42
Eleventy (Incremental)0.46

BSSG

BSSG - https://bssg.dragas.net/

Bash Static Site Generator (BSSG) is an SSG created by Stefano Marinelli. BSSG is written in the Bash shell.

BSSG is a relatively new SSG. The first public release of BSSG was in March 2025 but there have been 14 subsequent releases.

BSSG includes a broad range of themes, support for incremental builds, parallel processing and a post article editor to manage content.

BSSG doesn't currently support 'Categories' so all existing 'Categories' were migrated to 'Tags'.

It is possible this skewed the data set slightly and adversely affected performance as it resulted in four tags having a lot of associated posts. BSSG can list all tags with article counts using the 'bssg.sh tags' command.

TagCount
blogging236
football112
software122
UK260
$ bssg.sh
BSSG - Bash Static Site Generator (v0.32)
$ bash --version
GNU bash, version 5.3.3(1)-release (x86_64-pc-linux-gnu)

Initial BSSG build from scratch.

$ bssg.sh build

BBSG uses incremental builds and only rebuilds what has changed.

ThemeTime (secs)Notes
Default2,389Full (2,389 secs = 39 mins)
Default23Unchanged.
Default61Add new post (no tags).
Default100Add new post (existing tag).
Default62Modify existing post.
Default107Add existing tag to existing post.
Default83Add new tag to existing post.

By default, BSSG generates related posts based on the 'Tags' in each post. The default number of related posts displayed is 3. If this feature is disabled, then the build time is reduced significantly.

ThemeTime (secs)Notes
Default169Full
Default12Unchanged.
Default63Add new post (no tags).
Default62Add new post (existing tag).
Default64Modify existing post.
Default62Add existing tag to existing post.
Default70Add new tag to existing post.

BSSG also supports parallel processing using the GNU parallel shell tool. The GNU parallel package is very lightweight (< 1MB).

BSSG detects the presence of GNU parallel automatically and spawns N processes in parallel where N is the number of threads available.

Checked dependencies. Parallel available: true
GNU parallel found! Using parallel processing.

On my computer, this resulted in BSSG spawning 8 Bash processes which may have been too many as the load average climbed to between 10 and 15.

However, the elapsed time for the initial build of a blog with 1,000 posts reduces from 39 minutes to under 10 minutes.

Before you exclaim '10 minutes when Hugo and Eleventy are sub-second', think about how often you completely rebuild every single post on your blog. Not very often.

The typical use case is writing a new blog post. There may be occasions when you change theme or spend two weeks consolidating all your tags and categories but, hopefully, those should be relatively rare.

ThemeTime (secs)Notes
Default559Full. Parallel.
Default32Unchanged.
Default60Add new post (no tags).
Default75Add new post (existing tag).
Default67Modify existing post.
Default73Add existing tag to existing post.
Default67Add new tag to existing post.

Removing 'Related Posts' and running in parallel reduces the time for a full build to 1 minute and an incremental build to 45 seconds.

ThemeTime (secs)Notes
Default59Full. Parallel.
Default30Unchanged.
Default44Add new post (no tags).
Default44Add new post (existing tag).

One big advantage of BSSG is the ability to quickly and easily change themes. You simply select a theme, modify the THEME entry in the configuration file and it just works. This is because BSSG themes use a single CSS style sheet. This may limit the functionality available but it just works.

Zola

Zola - https://www.getzola.org/

Zola is a SSG written in Rust. Like Hugo, Zola is a single executable. Like Hugo, Zola is fast. Like Hugo, changing themes in Zola is not simply a case of modifying the THEME entry in 'config.toml'. Each theme seems to have additional, custom configuration options that need to be set.

$ zola --version
zola 0.21.0
$ rustc --version
rustc 1.90.0 (1159e78c4 2025-09-14) (Arch Linux rust 1:1.90.0-3)

Serene Theme - https://github.com/isunjn/serene

Building the blog

$ zola build

The Zola build time for 1,000 posts was so lightning fast, I had to check it actually worked !

$ zola build
Building site...
Checking all internal links with anchors.
> Successfully checked 0 internal link(s) with anchors.
-> Creating 1030 pages (0 orphan) and 1 sections
Done in 351ms.

Like Hugo, Zola also has a live development server that watches for changes to the site in real-time. This is also fast.

Building site...
Checking all internal links with anchors.
> Successfully checked 0 internal link(s) with anchors.
-> Creating 1031 pages (0 orphan) and 1 sections
Done in 309ms.

Listening for changes in zola-blog/{config.toml,content,sass,static,templates,themes}

Web server is available at http://127.0.0.1:1111 (bound to 127.0.0.1:1111)

Change detected @ 2025-10-14 13:17:09
-> Content changed zola-blog/content/posts/zola-new-post.md
Checking all internal links with anchors.
> Successfully checked 0 internal link(s) with anchors.
-> Creating 1031 pages (0 orphan) and 1 sections
Done in 283ms.

Finally I experimented with a couple more themes.

Linkita - https://www.getzola.org/themes/linkita/

BearBlog - https://www.getzola.org/themes/bearblog/

PaperMod - https://www.getzola.org/themes/papermod/

ThemeTime (secs)Notes
Serene0.35Full
Serene0.28Incremental
Linkita1.77Full
Linkita1.70Incremental
Bearblog0.26Full
Bearblog0.25Incremental
PaperMod20.70Full
PaperMod20.51Incremental

Nikola

Nikola is a long established SSG (first released in 2012) written in Python.

Nikola - https://getnikola.com/blog/

$ python -V
Python 3.13.7
$ nikola version
Nikola v8.3.3

Useful Nikola commands.

nikola build
nikola serve --browser
nikola auto

To force a full rebuild in Nikola, you need to remove the 'output' directory.

You also need to use the Linux time command to get the elapsed timings for the nikola build command.

Nikola includes the wonderful blog.txt theme (originally written for Wordpress by Scott Wallick) so kudos to Nikola's author Roberto Alsina for that.

ThemeTime (secs)Notes
Default44.86Full
Default4.72Unchanged
Default5.86Add new post (no tags).
Default5.75Add new post (existing tag).
Default5.98Modify existing post.
Default5.87Add existing tag to existing post.
Default5.70Add new tag to existing post.
blogtxt47.34Full
blogtxt4.93Unchanged
blogtxt4.78Add new post (no tags).
blogtxt4.82Add new post (existing tag).

Pelican

Pelican - https://getpelican.com/

Create a dedicated virtual environment for Pelican.

$ workon Pelican
(Pelican) $ python -V
Python 3.13.7
(Pelican) $ pelican --version
4.11.0

Pelican doesn't have separate build and server commands. You simply run the development server which builds the site and watches for any changes.

(Pelican) $ pelican --autoreload --listen
Serving site at: http://127.0.0.1:8000 - Tap CTRL-C to stop
Done: Processed 1034 articles, 0 drafts, 0 hidden articles, 0 pages,
0 hidden pages and 0 draft pages in 3.65 seconds.

Add a new post (incremental build).

-> Modified: pelican-blog/content/my-pelican-post.md.
re-generating...
Done: Processed 1035 articles, 0 drafts, 0 hidden articles, 0 pages,
0 hidden pages and 0 draft pages in 2.96 seconds.

Summary

ThemeTime (secs)Notes
Default3.65Full
Default2.96Incremental

Jekyll

Ruby based blog.

$ ruby -v
ruby 3.4.6 (2025-09-16 revision dbd83256b1) +PRISM [x86_64-linux]
$ bundle exec jekyll -v
jekyll 4.4.1

Jekyll base theme (minima) - https://github.com/jekyll/minima

Build the blog

$ bundle exec jekyll serve
<snip>
Run in verbose mode to see all warnings.
                    done in 2.788 seconds.
Auto-regeneration: enabled for '/home/andy/devel/my-jekyll-blog'
Server address: http://127.0.0.1:4000/

Live reload uses a different command and port

Run in verbose mode to see all warnings.
                    done in 4.7 seconds.
 Auto-regeneration: enabled for 'devel/my-jekyll-blog'
LiveReload address: http://127.0.0.1:35729
    Server address: http://127.0.0.1:4000/
  Server running... press ctrl-c to stop.

Jekyll also produces a lot of warnings (deprecation) that clutter up the display. This is surprising (and irritating) for the latest version of Jekyll and the standard, bundled theme.

There is a '--quiet' option for 'jekyll build' but this doesn't appear to silence the warnings.

Attempting to access the live development server on port 35729 fails. However, the live reload is actually available on port 4000.

This port only serves livereload.js over HTTP.

Given Jekyll was first released back in 2008, Jekyll feels rather neglected and outdated to me. Tags didn't work properly. All tags were processed and listed but the click through from an individual article as '404 - Not Found' error.

Also Jekyll insists on blog posts following a naming convention ('yyyy-mm-dd-title.md').

ThemeTime (secs)Notes
Default5.091Full
Default1.029Incremental
Default8.561Live reload

Useful SSG performance resources

Zach Leatherman (Eleventy lead developer) performed some performance benchmarks (in 2022) which are a useful benchmark comparing SSG's for pure Markdown conversion throughput for large sites.

However, Zach's tests don't include meta-data (tags, categories, dates) so aren't necessarily representative of a real-life blog or site.

https://www.zachleat.com/web/build-benchmark/

Generating representative test data is difficult but this Bash script scrapes a random Wikipedia page and generates Markdown (including tags and categories).

https://gist.github.com/jgreely/2338c72c825d2a93713e4f0fc0025985

Each SSG has its own format for front-matter. There are even two different formats for front matter; TOML and YAML.

Hugo has a very useful built-in conversion function to convert the Hugo front matter an all posts between the formats (including JSON).

$ hugo convert --help
Usage:
  hugo convert [command]

Available Commands:
  toJSON      Convert front matter to JSON
  toTOML      Convert front matter to TOML
  toYAML      Convert front matter to YAML

Hugo blog now hosted on Netlify

This blog uses Hugo and was previously hosted on Amazon S3 storage. The traffic and hence the costs were minimal (zero).

After recently having to completely re-install Arch Linux after an idiotic mistake, I realised that Hugo was out of date, my Hugo theme was out of date and I'd forgotten precisely how the deployment to S3 actually worked.

I was toying with taking my ball home in a mindless fit of pique, migrating 1,000 posts to Eleventy and I also looked at the Publii static site CMS with interest.

However, that would have been foolish as I already had a Hugo blog that worked fine. The problem was I never actually used it. It's frictionless blogging but you have to actually produce content occasionally. The friction (for me at least) is typing the words in - not building, previewing and publishing the site.

So, in the great blog unification process, I resurrected all my historical blog posts, my very limited content on write.as and deposited the lot into Hugo.

I changed the theme to PaperMod as it was a modern, clean, minimal, single column theme reminiscent of write.as.

The migration was pretty straightforward as all the existing posts were already in Markdown format and the YAML front matter just needed tweaking.

As I had used Hugo and Netlify for a friend's conventional Web site, I took the opportunity to switch the blog from S3 to Netlify which gives me SSL support and is generally a 'one click' operation to push the content to GitHub and then publish on Netlify.

Another blog migration

It all started innocuously enough with this post from Alex Shroeder

https://octodon.social/@kensanata/101052266709264418

Writing tools.
1. Emacs
2. Wiki
What about you ?

I spontaneously replied.

Emacs
Orgmode
Nikola

This reminded me that since, I had recently migrated my desktop from Arch Linux to Fedora 29, I needed to reinstall Nikola and check that the blog I never use still could be built successfully.

Oh - how exciting. Nikola has recently released version 8.0.1 and I was on the previous version - 7.8.15. I quickly created a Python 3 virtual environment and installed Nikola.

I generated my site as normal but encountered an error. One post failed to be processed correctly. This was strange so I created another virtual environment and tried using the tried and trusted Nikola 7.8.15 which I knew worked. Definitely.

Only, inevitably, Nikola 7.8.15 also failed. Oh well, a lot has changed since I last posted to my blog way back in January 2017. The version of Emacs has changed, the version of orgmode has changed. I examined the blog entry that was causing a problem. It was a fairly standard text article with a single source code block. As the source block was 'BASIC', the language wasn't explicitly specified. This isn't a problem in orgmode normally but the Nikola orgmode plugin got confused so I just pretended the code snippet was 'C' and everything worked again.

As I was researching the issue, I noticed that another static site generator, Hugo, had also added native orgmode support over a year ago. I had previously experimented with Hugo and found it was incredibly fast to generate my site - even when I added in my entire blog output (978 posts).

Clearly, there was no point whatsoever in experimenting with the Hugo orgmode support for a blog I never used any more. So I went ahead and did so anyway and found the Hugo orgmode support was pretty good. The orgmode headers were supported whereas Nikola used a comment section for the front matter.

Actually, there was a reason for this resurrected interest in maintaining a blog. After Google decided to pull the plug on Google Plus, I had ditched that platform in a fit of pique and experimented with Diaspora for longer form articles and Mastodon for microblogging.

The problem with Diaspora is that it doesn't currently federate with the ActivityPub protocol (which includes Mastodon sites) and the other problem is that, just like Google, it could disappear.

A Mastodon/Pleroma instance with no character limit might solve the problem but, to be honest, I prefer to read longer articles on a blog.

So I think there is still a place for a self-hosted blog, complete with an RSS feed.

What I have learned however is that blog migrations are still problematic and time-consuming. Even converting from a Markdown blog to another Markdown blog, the differences in the meta-data (categories, tags), inevitably no-one has though to standardise on a single, universal timestamp format and images (no matter where you locate them) are always a problem so there will always be some sort of migration effort required.

To guard against this, I have re-converted from orgmode to Markdown and my front-matter now consists solely of:-

---
title: "Another blog migration"
date: 2018-11-14T10:43:58Z
---

No categories, no tags, no author, no description, no keywords, no slugs, no comments.

Just words.