It’s pretty neat that we’ve come full circle from writing HTML/CSS ourselves, to using behemoth server-side scripting to calculate the markup for us on-the-fly, to using zombie javascript to staticly compile it on demand.

I made this site to make use of my long vacant domain and to get to grips with static site generation. I figured I’d throw in some Codespaces and GitHub Actions too.

It was remarkably simple to setup and get it deploying to my dodgy shared hosting via GitHub Actions.

I’ll try and fill this out with some proper instructions once I’ve polished it a bit, but as a barebones start.

Follow the instructions at https://gohugo.io/getting-started/quick-start/ to get hugo up and running in a repository or GitHub Codespace.

devcontainer.json

Chuck this at .devcontainer/devcontainer.json to get a hugo-ready Codespace every time

Note (Updated 2025): This example has been updated to use the latest devcontainer image and best practices. The original used universal:2 which is now deprecated.

{
  "name": "Hugo Site Development",
  "image": "mcr.microsoft.com/devcontainers/universal:3",
  "features": {
    "ghcr.io/devcontainers/features/hugo:1": {
      "version": "latest",
      "extended": true
    },
    "ghcr.io/devcontainers/features/go:1": {
      "version": "latest"
    },
    "ghcr.io/devcontainers/features/git:1": {
      "version": "latest"
    }
  },
  "postCreateCommand": "hugo mod get -u && hugo server -D -b=\"https://${CODESPACE_NAME}-1313.preview.app.github.dev/\" --appendPort=false",
  "forwardPorts": [1313],
  "portsAttributes": {
    "1313": {
      "label": "Hugo Server",
      "onAutoForward": "notify"
    }
  }
}

deploy-hugo-ftp.yml

Here’s an example GitHub Action that deploys your changes as you push them :) Chuck it in .github/workflows/deploy-hugo-ftp.yml

name: deploy-hugo-ftp

on:
  push:
    branches:
      - main  # Set a branch to deploy
  pull_request:

jobs:
  deploy:
    runs-on: ubuntu-22.04
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
    steps:
      - uses: actions/checkout@v3
        with:
          submodules: true  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: '0.110.0'
          # extended: true

      - name: Build
        run: hugo --minify

      - name: Deploy
        uses: SamKirkland/FTP-Deploy-Action@v4.3.4
        with:
          server: ${{ secrets.FTP_SERVER }}
          username: ${{ secrets.FTP_USERNAME }}
          password: ${{ secrets.FTP_PASSWORD }}
          local-dir: ./public/
          remote-dir: /public_html/
          protocol: ftp

Thanks ♥️