title:Deploying a Hugo Site to Neocities with GitHub Actions
tags:["all", "hugo", "meta", "serverless"]

I came across Neocities many months ago, and got really excited by the premise: a free web host with the mission to bring back the "fun, creativity and independence that made the web great." I spent a while scrolling through the gallery of personal sites and was amazed by both the nostalgic vibes and the creativity on display. It's like a portal back to when the web was fun. Neocities seemed like something I wanted to be a part of so I signed up for an account... and soon realized that I didn't really want to go back to crafting artisinal HTML by hand like I did in the early '00s. I didn't see an easy way to leverage my preferred static site generator1 so I filed it away and moved on.

Until yesterday, when I saw a post from Sophie on How I deploy my Eleventy site to Neocities. I hadn't realized that Neocities had an API, or that there was a deploy-to-neocities GitHub Action which uses that API to push content to Neocities. With that new-to-me information, I thought I'd give Neocities another try - a real one this time.

I had been hosting this site on Netlify's free plan for a couple of years and haven't really encountered any problems. But I saw Neocities as a better vision of the internet, and I wanted to be a part of that2. So last night I upgraded to the $5/month Neocities Supporter plan which would let me use a custom domain for my site (along with higher storage and bandwidth limits).

I knew I'd need to make some changes to Sophie's workflow since my site is built with Hugo rather than Eleventy. I did some poking around and found GitHub Actions for Hugo which would take care of installing Hugo for me. Then I'd just need to render the HTML with hugo --minify and use the Torchlight CLI to mark up the code blocks. Along the way, I also discovered that I'd need to overwrite /not_found.html to insert my custom 404 page so I included an extra step to do that. After that, I'll finally be ready to push the results to Neocities.

It took a bit of trial and error, but I eventually adapted this workflow which does the trick:

The Workflow

1# .github/workflows/deploy-to-neocities.yml
2name: Deploy to Neocities
5 # Daily build to catch any future-dated posts
6 schedule:
7 - cron: 0 13 * * *
8 # Build on pushes to the main branch only
9 push:
10 branches:
11 - main
14 group: deploy-to-neocities
15 cancel-in-progress: true
18 run:
19 shell: bash
22 deploy:
23 name: Build and deploy Hugo site
24 runs-on: ubuntu-latest
25 steps:
26 # Install Hugo in the runner
27 - name: Hugo setup
28 uses: peaceiris/[email protected]
29 with:
30 hugo-version: '0.121.1'
31 extended: true
32 # Check out the source for the site
33 - name: Checkout
34 uses: actions/checkout@v4
35 with:
36 submodules: recursive
37 # Build the site with Hugo
38 - name: Build with Hugo
39 run: hugo --minify
40 # Copy my custom 404 page to not_found.html so it
41 # will be picked up by Neocities
42 - name: Insert 404 page
43 run: |
44 cp public/404/index.html public/not_found.html
45 # Highlight code blocks with the Torchlight CLI
46 - name: Highlight with Torchlight
47 run: |
48 npm i @torchlight-api/torchlight-cli
49 npx torchlight
50 # Push the rendered site to Neocities and
51 # clean up any orphaned files
52 - name: Deploy to Neocities
53 uses: bcomnes/deploy-to-neocities@v1
54 with:
55 api_token: ${{ secrets.NEOCITIES_API_TOKEN }}
56 cleanup: true
57 dist_dir: public

I'm thrilled with how well this works, and happy to have learned a bit more about GitHub Actions in the process. Big thanks to Sophie for pointing me in the right direction!

  1. Also I'm kind of lazy, and not actually very good at web design anyway. I mean, you've seen my work. ↩︎

  2. Plus I love supporting passion projects. ↩︎

Celebrate this post: