Hugo Cactus Theme Tweaks and Deploying Using Neocities CLI

I decided to use Hugo to generate my blog, since it builds quickly and comes bundled with all the necessary dependencies. I chose the Cactus theme for its aesthetics and readability, but I made some tweaks to it before publishing. Here’s what I did:

Automatic Dark Mode

The Cactus theme came bundled with four themes: Dark, White, Light, and Classic. I could manually set any of these, but I wanted my blog to switch colour schemes between Dark and Light automatically depending on the user’s operating system theme settings. The CSS prefers-color-scheme feature looked like exactly what I needed to implement this.

I ran into a challenge when I figured out that the Cactus theme’s colours are set using SCSS variables. As explained here, SCSS code needs to be converted (i.e. compiled) into CSS code before the browser can use it. After this conversion happens, the SCSS variables no longer exist, so they can’t be changed at runtime using queries like prefers-color-scheme. CSS custom properties, on the other hand, can be changed at runtime, so they respond to prefers-color-scheme just fine. I just had to turn all of my SCSS colour variables into CSS custom properties, and I would achieve the automatic dark mode I wanted.

I started by making a new css folder in the Cactus theme’s static folder. In this folder, I made a file called colors.css, which contained the following code:

@media (prefers-color-scheme: light) {
    :root {
        /* based on colours from assets/scss/colors/white.scss */
        --color-background: #FFFFFF;
        --color-footer-mobile-1:  color-mix(in srgb, var(--color-background), #000 2%);
        --color-footer-mobile-2: color-mix(in srgb, var(--color-background), #000 10%);
        --color-background-code: color-mix(in srgb, var(--color-background), #000 2%);
        --color-border: #666;
        --color-meta: #666;
        --color-meta-code: color-mix(in srgb, var(--color-meta), #fff 10%);
        --color-link: rgba(212, 128, 170, 1);
        --color-text: #383838
        --color-accent-3: #8c8c8c;
        --color-accent-2: #383838;
        --color-accent-1: #2bbc8a;
        --color-quote: #2bbc8a;
    }
}
@media (prefers-color-scheme: dark) {
    :root {
        /* based on colours from assets/scss/colors/dark.scss */
        --color-background: #1d1f21;
        --color-footer-mobile-1: color-mix(in srgb, var(--color-background), #fff 2%);
        --color-footer-mobile-2: color-mix(in srgb, var(--color-background), #fff 10%);
        --color-background-code: color-mix(in srgb, var(--color-background), #fff 2%);
        --color-border: #666;
        --color-meta: #666;
        --color-meta-code: #666;
        --color-link: rgba(212, 128, 170, 1);
        --color-text: #c9cacc;
        --color-accent-3: #cccccc;
        --color-accent-2: #eeeeee;
        --color-accent-1: #2bbc8a;
        --color-quote: #ccffb6;
    }
}

CSS doesn’t have darken or lighten functions like SCSS does, so I replaced them all with color-mix function calls and it produced the same effect. To replace darken I mixed with black, and to replace lighten I mixed with white.

I then removed all the SCSS files in the Cactus theme’s assets/colors folder, and used the following regular expressions to replace all of the SCSS variable calls in the Cactus theme folder with CSS custom property calls:

  • Search: \$color-([-\w+]+)
  • Replace: var(--color-$1)

As an example, this would replace all instances of $color-accent-3 with var(--color-accent-3).

Dark Mode-Compliant Syntax Highlighting

I’ll be posting a lot of code on this blog, so I wanted to give my syntax highlighting an automatic dark or light theme as well. I started by putting the following small block of code in my hugo.toml file:

[markup]
    [markup.highlight]
        noClasses = false

This would allow me to use custom syntax highlighting classes. Hugo uses Chroma for syntax highlighting, and the Chroma Playground gave me a good idea of what colour schemes were available. I chose Catppuccin Latte for light mode, and Catppuccin Mocha for dark mode. I generated the classes in one file using commands adapted from here:

cd themes/cactus/static/css
hugo gen chromastyles --style="catppuccin-latte" > syntax.css
echo "@media (prefers-color-scheme: dark) {" >> syntax.css
hugo gen chromastyles --style="catppuccin-mocha" >> syntax.css
echo "}" >> syntax.css

And that was it! My automatic dark mode with automatic syntax highlighting was successfully implemented.

Removing Unnecessary Space

I discovered there was extra whitespace in between the list elements almost everywhere my blog’s navigation appeared. According to this StackOverflow question I found, this is a common issue with inline list items. The fix that worked for me was setting the ul font size to 0 and setting the li font size back to the required size.

Whitespace example

There was also a grey border at the top of the website that was especially apparent when the dark theme was activated. I removed it by deleting border-top: 2px solid $color-text; from layouts/partials/head.html.

Reducing CSS Filename Length

Neocities only accepts file names of a certain length. Hugo was generating CSS style templates that had SHA512 fingerprints in the file names. This was too long for Neocities, so I replaced the code snippet resources.Fingerprint "sha512" with resources.Fingerprint "sha256" in layouts/partials/head.html.

Site Building Error Fix

When first building the blog using hugo serve, I got a no such template "_internal/google_analytics_async.html" error. I fixed this by removing the following block of code from head.html:

  {{ if .Site.GoogleAnalytics }}
  {{ if .Site.Params.googleAnalyticsAsync }}
    {{ template "_internal/google_analytics_async.html" . }}
  {{ else }}
    {{ template "_internal/google_analytics.html" . }}
  {{ end }}
  {{ end }}

Neocities CLI

Now that my blog was ready, it was time to publish it. I chose Neocities as a hosting platform: it’s free to host, ad-free, and I admire their mission of making it easier for anyone to make their own static website. They also provide a command-line tool for editing your website called the Neocities CLI. Once I installed the CLI, all I had to do was publish my finished website using the command hugo, and then upload the resulting public folder containing my published website to Neocities using the command neocities push public.

I’m pretty happy with how everything turned out. I hope this can be useful to someone building something similar! Now that my blog is up and running I’ll probably be making some posts about the home server I’m setting up, so stay tuned. Thanks for reading :-]