Published: Feb 9, 2023 by Isaac Johnson
Following our last few posts about CMS, I wanted to dig into Hugo a bit more. Hugo is an Open Source static site generator that follows similar systems like Jekyll (used here) and Octopress.
Today we will install Hugo and connect it to a CMS like Contentful. We’ll then generate a local static site before tackling a Github Workflow to build it in CI. We’ll jump into Azure Static Web Apps to show how we can use the free tier to host the blog in Azure. We’ll wrap up by tying in a custom domain from Azure DNS and using Github “Dispatch” triggers to trigger CICD directly from Contentful webhooks.
History and Origins
It was created in 2013 by Steve Francia (spf13). He wanted to create a fast flexible site generator with themes and plugins written in Go.
In 2016, Steve released to it to be maintained by OS volunteers as it continues to evolve and grow. *In looking up Steve, I found he even has his own VIM Distribution. If you look up his profile he has had leadership roles in 5 of the top 100 OS projects including Drupal, MongoDB, Hugo, Docker and Go).
Install Hugo
builder@DESKTOP-72D2D9T:~/Workspaces$ mkdir hugoBlog
builder@DESKTOP-72D2D9T:~/Workspaces$ cd hugoBlog/
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog$ sudo apt update && sudo apt install -y hugo
[sudo] password for builder:
Hit:1 http://archive.ubuntu.com/ubuntu focal InRelease
Get:2 https://apt.releases.hashicorp.com focal InRelease [17.1 kB]
Get:3 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:4 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:5 https://packages.microsoft.com/repos/azure-cli focal InRelease [3029 B]
Get:6 https://packages.cloud.google.com/apt cloud-sdk InRelease [6361 B]
Get:7 https://packages.microsoft.com/repos/code stable InRelease [3023 B]
Get:8 http://archive.ubuntu.com/ubuntu focal-backports InRelease [108 kB]
Err:2 https://apt.releases.hashicorp.com focal InRelease
The following signatures couldn't be verified because the public key is not available: NO_PUBKEY AA16FCBCA621E701
Get:10 https://packages.microsoft.com/repos/azure-cli focal/main all Packages [4043 B]
Err:6 https://packages.cloud.google.com/apt cloud-sdk InRelease
The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
Get:11 https://packages.microsoft.com/repos/code stable/main amd64 Packages [58.5 kB]
Get:12 https://packages.microsoft.com/repos/code stable/main armhf Packages [59.1 kB]
Get:13 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages [2345 kB]
Get:14 https://packages.microsoft.com/repos/code stable/main arm64 Packages [58.9 kB]
Get:15 http://archive.ubuntu.com/ubuntu focal-updates/main Translation-en [405 kB]
Get:16 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 c-n-f Metadata [16.3 kB]
Get:17 http://archive.ubuntu.com/ubuntu focal-updates/restricted amd64 Packages [1564 kB]
Get:18 http://archive.ubuntu.com/ubuntu focal-updates/restricted Translation-en [221 kB]
Get:19 http://archive.ubuntu.com/ubuntu focal-updates/restricted amd64 c-n-f Metadata [620 B]
Get:20 http://archive.ubuntu.com/ubuntu focal-updates/universe amd64 Packages [1021 kB]
Get:21 http://archive.ubuntu.com/ubuntu focal-updates/universe Translation-en [237 kB]
Get:22 http://archive.ubuntu.com/ubuntu focal-updates/universe amd64 c-n-f Metadata [23.5 kB]
Get:23 http://archive.ubuntu.com/ubuntu focal-backports/universe amd64 Packages [24.9 kB]
Get:24 http://archive.ubuntu.com/ubuntu focal-backports/universe amd64 c-n-f Metadata [880 B]
Get:25 http://security.ubuntu.com/ubuntu focal-security/main amd64 Packages [1968 kB]
Get:9 https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/Debian_Testing InRelease [1275 B]
Err:9 https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/Debian_Testing InRelease
The following signatures were invalid: EXPKEYSIG 4D64390375060AA4 devel:kubic OBS Project <devel:kubic@build.opensuse.org>
Get:26 http://security.ubuntu.com/ubuntu focal-security/main Translation-en [322 kB]
Get:27 http://security.ubuntu.com/ubuntu focal-security/main amd64 c-n-f Metadata [12.0 kB]
Get:28 http://security.ubuntu.com/ubuntu focal-security/restricted amd64 Packages [1467 kB]
Get:29 http://security.ubuntu.com/ubuntu focal-security/restricted Translation-en [207 kB]
.opensuse.org/repositories/devel:kubic:libcontainers:unstable/Debian_Testing InRelease: The following signatures were invalid: EXPKEYSIG 4D64390375060AA4 devel:kubic OBS Project <devel:kubic@build.opensuse.org>
W: Failed to fetch https://apt.releases.hashicorp.com/dists/focal/InRelease The following signatures couldn't be verified because the public key is not available: NO_PUBKEY AA16FCBCA621E701
W: Failed to fetch https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/Debian_Testing/InRelease The following signatures were invalid: EXPKEYSIG 4D64390375060AA4 devel:kubic OBS Project <devel:kubic@build.opensuse.org>
W: Failed to fetch https://packages.cloud.google.com/apt/dists/cloud-sdk/InRelease The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B53DC80D13EDEF05
W: Some index files failed to download. They have been ignored, or old ones used instead.
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
libfwupdplugin1 libgbm1 libjs-sphinxdoc libjs-underscore libsecret-1-0 libsecret-common libwayland-server0 libxmlb1 python-pkginfo-doc python3-adal
python3-aiohttp python3-applicationinsights python3-argcomplete python3-async-timeout python3-azext-devops python3-azure python3-azure-cli
python3-azure-cli-core python3-azure-cli-telemetry python3-azure-cosmos python3-azure-cosmosdb-table python3-azure-datalake-store
python3-azure-functions-devops-build python3-azure-multiapi-storage python3-azure-storage python3-bcrypt python3-cffi python3-fabric
python3-humanfriendly python3-invoke python3-isodate python3-javaproperties python3-jsmin python3-jsondiff python3-knack python3-mock python3-msal
python3-msal-extensions python3-msrest python3-msrestazure python3-multidict python3-paramiko python3-pbr python3-pkginfo python3-ply
python3-portalocker python3-psutil python3-pycparser python3-requests-oauthlib python3-scp python3-sshtunnel python3-tabulate python3-tz python3-uamqp
python3-vsts-cd-manager python3-websocket python3-xmltodict python3-yarl
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
libsass1
The following NEW packages will be installed:
hugo libsass1
0 upgraded, 2 newly installed, 0 to remove and 103 not upgraded.
Need to get 10.6 MB of archives.
After this operation, 47.5 MB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu focal/universe amd64 libsass1 amd64 3.6.3-1ubuntu1 [684 kB]
Get:2 http://archive.ubuntu.com/ubuntu focal/universe amd64 hugo amd64 0.68.3-1 [9893 kB]
Fetched 10.6 MB in 1s (8740 kB/s)
Selecting previously unselected package libsass1:amd64.
(Reading database ... 191611 files and directories currently installed.)
Preparing to unpack .../libsass1_3.6.3-1ubuntu1_amd64.deb ...
Unpacking libsass1:amd64 (3.6.3-1ubuntu1) ...
Selecting previously unselected package hugo.
Preparing to unpack .../hugo_0.68.3-1_amd64.deb ...
Unpacking hugo (0.68.3-1) ...
Setting up libsass1:amd64 (3.6.3-1ubuntu1) ...
Setting up hugo (0.68.3-1) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.9) ...
/sbin/ldconfig.real: /usr/lib/wsl/lib/libcuda.so.1 is not a symbolic link
We now create a new Hugo site
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog$ hugo new site myBlog
Congratulations! Your new Hugo site is created in /home/builder/Workspaces/hugoBlog/myBlog.
Just a few more steps and you're ready to go:
1. Download a theme into the same-named folder.
Choose a theme from https://themes.gohugo.io/ or
create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
with "hugo new <SECTIONNAME>/<FILENAME>.<FORMAT>".
3. Start the built-in live server via "hugo server".
Visit https://gohugo.io/ for quickstart guide and full documentation.
Then go in there and add a theme
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog$ cd myBlog/
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ git init
Initialized empty Git repository in /home/builder/Workspaces/hugoBlog/myBlog/.git/
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ git checkout -b main
Switched to a new branch 'main'
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ git submodule add https://github.com/panr/hugo-theme-terminal themes/terminal
Cloning into '/home/builder/Workspaces/hugoBlog/myBlog/themes/terminal'...
remote: Enumerating objects: 2796, done.
remote: Counting objects: 100% (257/257), done.
remote: Compressing objects: 100% (159/159), done.
remote: Total 2796 (delta 125), reused 199 (delta 93), pack-reused 2539
Receiving objects: 100% (2796/2796), 3.51 MiB | 5.85 MiB/s, done.
Resolving deltas: 100% (1578/1578), done.
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ echo "theme = 'terminal'" >> config.toml
I found the apt install hugo is too old
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ hugo server
Building sites … ERROR 2023/02/04 17:54:43 render of "home" failed: execute of template failed: template: _default/index.html:22:7: executing "footer" at <partial "footer.html" .>: error calling partial: "/home/builder/Workspaces/hugoBlog/myBlog/themes/terminal/layouts/partials/footer.html:15:41": execute of template failed: template: partials/footer.html:15:41: executing "partials/footer.html" at <js>: can't evaluate field Build in type string
ERROR 2023/02/04 17:54:43 render of "taxonomyTerm" failed: execute of template failed: template: _default/terms.html:22:7: executing "footer" at <partial "footer.html" .>: error calling partial: "/home/builder/Workspaces/hugoBlog/myBlog/themes/terminal/layouts/partials/footer.html:15:41": execute of template failed: template: partials/footer.html:15:41: executing "partials/footer.html" at <js>: can't evaluate field Build in type string
Built in 85 ms
Error: Error building site: failed to render pages: render of "taxonomyTerm" failed: execute of template failed: template: _default/terms.html:22:7: executing "footer" at <partial "footer.html" .>: error calling partial: "/home/builder/Workspaces/hugoBlog/myBlog/themes/terminal/layouts/partials/footer.html:15:41": execute of template failed: template: partials/footer.html:15:41: executing "partials/footer.html" at <js>: can't evaluate field Build in type string
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ hugo version
Hugo Static Site Generator v0.68.3/extended linux/amd64 BuildDate: 2020-03-25T06:15:45Z
I did an apt remove and install with homebrew instead
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ sudo apt remove hugo
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
libfwupdplugin1 libgbm1 libjs-sphinxdoc libjs-underscore libsass1 libsecret-1-0 libsecret-common libwayland-server0 libxmlb1 python-pkginfo-doc
python3-adal python3-aiohttp python3-applicationinsights python3-argcomplete python3-async-timeout python3-azext-devops python3-azure python3-azure-cli
python3-azure-cli-core python3-azure-cli-telemetry python3-azure-cosmos python3-azure-cosmosdb-table python3-azure-datalake-store
python3-azure-functions-devops-build python3-azure-multiapi-storage python3-azure-storage python3-bcrypt python3-cffi python3-fabric
python3-humanfriendly python3-invoke python3-isodate python3-javaproperties python3-jsmin python3-jsondiff python3-knack python3-mock python3-msal
python3-msal-extensions python3-msrest python3-msrestazure python3-multidict python3-paramiko python3-pbr python3-pkginfo python3-ply
python3-portalocker python3-psutil python3-pycparser python3-requests-oauthlib python3-scp python3-sshtunnel python3-tabulate python3-tz python3-uamqp
python3-vsts-cd-manager python3-websocket python3-xmltodict python3-yarl
Use 'sudo apt autoremove' to remove them.
The following packages will be REMOVED:
hugo
0 upgraded, 0 newly installed, 1 to remove and 103 not upgraded.
After this operation, 44.7 MB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database ... 191657 files and directories currently installed.)
Removing hugo (0.68.3-1) ...
Processing triggers for man-db (2.9.1-1) ...
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ brew install hugo
Running `brew update --auto-update`...
==> Auto-updated Homebrew!
Updated 4 taps (codefresh-io/cli, homebrew/core, knative/client and knative-sandbox/kn-plugins).
==> New Formulae
akku grayskull php@8.1
ancient hermit pipdeptree
ansible@6 httm plz-cli
aptos ibazel podsync
aribb24 jbang portablegl
aws-sam-cli joker protolint
bindgen jreleaser prowler
bossa jscpd prs
brpc juicefs psysh
buf keploy qdmr
busted knative-sandbox/kn-plugins/admin@1.8 quartz-wm
bzip3 knative-sandbox/kn-plugins/event@1.8 retdec
cargo-about knative-sandbox/kn-plugins/func@1.8 rnr
cargo-deny knative-sandbox/kn-plugins/quickstart@1.8 ruby@3.1
cargo-make knative-sandbox/kn-plugins/source-kafka@1.8 ruff
cargo-release knative-sandbox/kn-plugins/source-kamelet@1.8 sapling
cascadia knative/client/kn@1.8 scriptisto
cdebug kubefirst secp256k1
cdsclient kubent seven-kingdoms
check-jsonschema kubevious simdutf
clang-build-analyzer kustomizer skaffold@1.39
clitest kwctl skeema
cloudflare-wrangler2 kwok snakefmt
clusterawsadm lemmeknow sniffnet
cntb libaribcaption socket_vmnet
cocogitto libemf2svg souffle
code-cli libfyaml spectral-cli
cog libisofs speedbump
conda-zsh-completion liblerc sql-language-server
copa libsais standard
corrosion licensed steampipe
countdown llama stepci
cpuid luacheck stuffbin
crfsuite m1ddc stylelint
d2 macpine syft
dotnet@6 mariadb@10.9 syslog-ng
dstack marksman temporal
dufs mdless tetra
ecoji metals totp-cli
emqx mimirtool tproxy
enpass-cli mpfrcx tut
envd naga-cli twm
erigon nap txt2man
evtx nemu unxip
fgbio oauth2c video-compare
flagd ocm waybackpy
gf okta-awscli wikibase-cli
ghc@9.2 opencl-clhpp-headers xcdiff
go-task openvino xinit
gobackup osv-scanner xmodmap
gokey pandemics xorg-server
grammarly-languageserver pari-nflistdata xrdb
grantlee pbzx zf
graphqxl pdf-diff zsh-autopair
You have 12 outdated formulae installed.
You can upgrade them with brew upgrade
or list them with brew outdated.
==> Fetching dependencies for hugo: linux-headers@5.15, mpfr, libmpc, xz, zlib and binutils
==> Fetching linux-headers@5.15
==> Downloading https://ghcr.io/v2/homebrew/core/linux-headers/5.15/manifests/5.15.91
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/linux-headers/5.15/blobs/sha256:29e9a9b48e71ea0bbb43b1ea6290b97d57a433fe0617f918e0d80b7bbe188260
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:29e9a9b48e71ea0bbb43b1ea6290b97d57a433fe0617f918e0d80b7bbe188260?se=202
######################################################################## 100.0%
==> Fetching mpfr
==> Downloading https://ghcr.io/v2/homebrew/core/mpfr/manifests/4.2.0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/mpfr/blobs/sha256:3e62ca94c057c73dfb08c6b7be42b3aaf0e338c9a422dbdd74695e1106c302a5
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:3e62ca94c057c73dfb08c6b7be42b3aaf0e338c9a422dbdd74695e1106c302a5?se=202
######################################################################## 100.0%
==> Fetching libmpc
==> Downloading https://ghcr.io/v2/homebrew/core/libmpc/manifests/1.3.1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libmpc/blobs/sha256:f6542ae5bcf643ca0c980c7000cde1585922e76be080b3cc3422dac0d4a50904
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:f6542ae5bcf643ca0c980c7000cde1585922e76be080b3cc3422dac0d4a50904?se=202
######################################################################## 100.0%
==> Fetching xz
==> Downloading https://ghcr.io/v2/homebrew/core/xz/manifests/5.4.1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/xz/blobs/sha256:a2e27545d92f5387a48182319b5233a42c9ce98bea335fc4cdf15c808ab1ea1b
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:a2e27545d92f5387a48182319b5233a42c9ce98bea335fc4cdf15c808ab1ea1b?se=202
######################################################################## 100.0%
==> Fetching zlib
==> Downloading https://ghcr.io/v2/homebrew/core/zlib/manifests/1.2.13
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/zlib/blobs/sha256:0082aa29a61507e237389ee4e9fb6a6ed0cbd5d341e3905527c089c88e730411
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:0082aa29a61507e237389ee4e9fb6a6ed0cbd5d341e3905527c089c88e730411?se=202
######################################################################## 100.0%
==> Fetching binutils
==> Downloading https://ghcr.io/v2/homebrew/core/binutils/manifests/2.40
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/binutils/blobs/sha256:f0917ab2fe7b72350deac1946dd8e937e0199292f05ab763c5f309822c04c195
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:f0917ab2fe7b72350deac1946dd8e937e0199292f05ab763c5f309822c04c195?se=202
######################################################################## 100.0%
==> Fetching hugo
==> Downloading https://ghcr.io/v2/homebrew/core/hugo/manifests/0.110.0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/hugo/blobs/sha256:4cb16974713723501f6e6035da715621691f9afe6aa8cce902c408a205f5f2cd
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:4cb16974713723501f6e6035da715621691f9afe6aa8cce902c408a205f5f2cd?se=202
######################################################################## 100.0%
==> Installing dependencies for hugo: linux-headers@5.15, mpfr, libmpc, xz, zlib and binutils
==> Installing hugo dependency: linux-headers@5.15
==> Pouring linux-headers@5.15--5.15.91.x86_64_linux.bottle.tar.gz
🍺 /home/linuxbrew/.linuxbrew/Cellar/linux-headers@5.15/5.15.91: 963 files, 5.7MB
==> Installing hugo dependency: mpfr
==> Pouring mpfr--4.2.0.x86_64_linux.bottle.tar.gz
🍺 /home/linuxbrew/.linuxbrew/Cellar/mpfr/4.2.0: 31 files, 3.9MB
==> Installing hugo dependency: libmpc
==> Pouring libmpc--1.3.1.x86_64_linux.bottle.tar.gz
🍺 /home/linuxbrew/.linuxbrew/Cellar/libmpc/1.3.1: 13 files, 638.6KB
==> Installing hugo dependency: xz
==> Pouring xz--5.4.1.x86_64_linux.bottle.tar.gz
🍺 /home/linuxbrew/.linuxbrew/Cellar/xz/5.4.1: 223 files, 3MB
==> Installing hugo dependency: zlib
==> Pouring zlib--1.2.13.x86_64_linux.bottle.tar.gz
🍺 /home/linuxbrew/.linuxbrew/Cellar/zlib/1.2.13: 13 files, 472.7KB
==> Installing hugo dependency: binutils
==> Pouring binutils--2.40.x86_64_linux.bottle.tar.gz
🍺 /home/linuxbrew/.linuxbrew/Cellar/binutils/2.40: 4,698 files, 462.5MB
==> Installing hugo
==> Pouring hugo--0.110.0.x86_64_linux.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
/home/linuxbrew/.linuxbrew/etc/bash_completion.d
==> Summary
🍺 /home/linuxbrew/.linuxbrew/Cellar/hugo/0.110.0: 48 files, 53.4MB
==> Running `brew cleanup hugo`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
Warning: The following dependents of upgraded formulae are outdated but will not
be upgraded because they are not bottled:
cf2
kn
quickstart
==> Upgrading 3 dependents of upgraded formulae:
Disable this behaviour by setting HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
go 1.19.1 -> 1.19.5, k9s 0.26.6 -> 0.27.2, kubernetes-cli 1.25.2 -> 1.26.1
==> Fetching go
==> Downloading https://ghcr.io/v2/homebrew/core/go/manifests/1.19.5
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/go/blobs/sha256:4060878a09c55ce7bd3b1093829a5e01622be31816c368f8fcaf07e38bca1fb9
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:4060878a09c55ce7bd3b1093829a5e01622be31816c368f8fcaf07e38bca1fb9?se=202
######################################################################## 100.0%
==> Fetching k9s
==> Downloading https://ghcr.io/v2/homebrew/core/k9s/manifests/0.27.2
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/k9s/blobs/sha256:a44ee7532ca79e8635c07cf7ac3b4a08f44b004ed1d968891b927ad9aee8801c
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:a44ee7532ca79e8635c07cf7ac3b4a08f44b004ed1d968891b927ad9aee8801c?se=202
######################################################################## 100.0%
==> Fetching kubernetes-cli
==> Downloading https://ghcr.io/v2/homebrew/core/kubernetes-cli/manifests/1.26.1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/kubernetes-cli/blobs/sha256:69d5374efc9321dc5c312e4d434b17d9b11c05e66aec480751d2ea23ef34947e
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:69d5374efc9321dc5c312e4d434b17d9b11c05e66aec480751d2ea23ef34947e?se=202
######################################################################## 100.0%
==> Upgrading go
1.19.1 -> 1.19.5
==> Pouring go--1.19.5.x86_64_linux.bottle.tar.gz
🍺 /home/linuxbrew/.linuxbrew/Cellar/go/1.19.5: 12,456 files, 592.6MB
==> Running `brew cleanup go`...
Removing: /home/linuxbrew/.linuxbrew/Cellar/go/1.19.1... (12,434 files, 591.9MB)
Removing: /home/builder/.cache/Homebrew/go--1.19.1... (176.8MB)
==> Upgrading k9s
0.26.6 -> 0.27.2
==> Pouring k9s--0.27.2.x86_64_linux.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
/home/linuxbrew/.linuxbrew/etc/bash_completion.d
==> Summary
🍺 /home/linuxbrew/.linuxbrew/Cellar/k9s/0.27.2: 9 files, 72.3MB
==> Running `brew cleanup k9s`...
Removing: /home/linuxbrew/.linuxbrew/Cellar/k9s/0.26.6... (9 files, 69.6MB)
Removing: /home/builder/.cache/Homebrew/k9s--0.26.6... (21.9MB)
==> Upgrading kubernetes-cli
1.25.2 -> 1.26.1
==> Pouring kubernetes-cli--1.26.1.x86_64_linux.bottle.tar.gz
🍺 /home/linuxbrew/.linuxbrew/Cellar/kubernetes-cli/1.26.1: 231 files, 46.8MB
==> Running `brew cleanup kubernetes-cli`...
Removing: /home/linuxbrew/.linuxbrew/Cellar/kubernetes-cli/1.25.2... (228 files, 43.9MB)
Removing: /home/builder/.cache/Homebrew/kubernetes-cli--1.25.2... (13.6MB)
==> Checking for dependents of upgraded formulae...
==> No broken dependents found!
==> `brew cleanup` has not been run in the last 30 days, running now...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
Removing: /home/linuxbrew/.linuxbrew/Cellar/binutils/2.39_1... (4,687 files, 370.5MB)
Removing: /home/builder/.cache/Homebrew/binutils--2.39_1... (70.7MB)
Removing: /home/builder/.cache/Homebrew/cf2--git... (193 files, 3MB)
Removing: /home/builder/.cache/Homebrew/gcc--12.2.0... (105.8MB)
Removing: /home/builder/.cache/Homebrew/glibc--2.35_1... (14MB)
Removing: /home/builder/.cache/Homebrew/gmp--6.2.1_1... (1.1MB)
Removing: /home/builder/.cache/Homebrew/isl--0.25... (2MB)
Removing: /home/builder/.cache/Homebrew/kn--knative-v1.7.0... (56MB)
Removing: /home/builder/.cache/Homebrew/kubectx--0.9.4... (11.3KB)
Removing: /home/linuxbrew/.linuxbrew/Cellar/libmpc/1.2.1... (13 files, 550.2KB)
Removing: /home/builder/.cache/Homebrew/libmpc--1.2.1... (147KB)
Removing: /home/linuxbrew/.linuxbrew/Cellar/linux-headers@5.15/5.15.57... (963 files, 5.7MB)
Removing: /home/builder/.cache/Homebrew/linux-headers@5.15--5.15.57... (1.5MB)
Removing: /home/builder/.cache/Homebrew/lz4--1.9.4... (277.5KB)
Removing: /home/linuxbrew/.linuxbrew/Cellar/mpfr/4.1.0... (31 files, 7.9MB)
Removing: /home/builder/.cache/Homebrew/mpfr--4.1.0... (3.2MB)
Removing: /home/builder/.cache/Homebrew/quickstart--v1.7.0... (4.3MB)
Removing: /home/linuxbrew/.linuxbrew/Cellar/xz/5.2.7... (151 files, 2.5MB)
Removing: /home/builder/.cache/Homebrew/xz--5.2.7... (666.9KB)
Removing: /home/linuxbrew/.linuxbrew/Cellar/zlib/1.2.12_1... (12 files, 470.7KB)
Removing: /home/builder/.cache/Homebrew/zlib--1.2.12_1... (170.3KB)
Removing: /home/builder/.cache/Homebrew/zstd--1.5.2... (967.4KB)
Removing: /home/builder/.cache/Homebrew/kubernetes-cli_bottle_manifest--1.25.2... (6.1KB)
Removing: /home/builder/.cache/Homebrew/isl_bottle_manifest--0.25... (6.7KB)
Removing: /home/builder/.cache/Homebrew/xz_bottle_manifest--5.2.6... (6.4KB)
Removing: /home/builder/.cache/Homebrew/mpfr_bottle_manifest--4.1.0... (8.0KB)
Removing: /home/builder/.cache/Homebrew/linux-headers@5.15_bottle_manifest--5.15.57-1... (1.9KB)
Removing: /home/builder/.cache/Homebrew/glibc_bottle_manifest--2.35_1... (2KB)
Removing: /home/builder/.cache/Homebrew/portable-ruby-2.6.8_1.x86_64_linux.bottle.tar.gz... (10.3MB)
Removing: /home/builder/.cache/Homebrew/binutils_bottle_manifest--2.39_1... (10.5KB)
Removing: /home/builder/.cache/Homebrew/kubectx_bottle_manifest--0.9.4... (1.9KB)
Removing: /home/builder/.cache/Homebrew/lz4_bottle_manifest--1.9.4... (6.3KB)
Removing: /home/builder/.cache/Homebrew/go_mod_cache... (45,445 files, 798.2MB)
Removing: /home/builder/.cache/Homebrew/kubernetes-cli_bottle_manifest--1.24.2... (6.1KB)
Removing: /home/builder/.cache/Homebrew/descriptions.json... (344.7KB)
Removing: /home/builder/.cache/Homebrew/go_cache... (7,324 files, 839.6MB)
Removing: /home/builder/.cache/Homebrew/xz_bottle_manifest--5.2.7... (6.4KB)
Removing: /home/builder/.cache/Homebrew/k9s_bottle_manifest--0.26.6... (6.1KB)
Removing: /home/builder/.cache/Homebrew/go_bottle_manifest--1.18.4... (7.3KB)
Removing: /home/builder/.cache/Homebrew/zlib_bottle_manifest--1.2.12_1... (6.3KB)
Removing: /home/builder/.cache/Homebrew/gcc_bottle_manifest--12.2.0-1... (10.8KB)
Removing: /home/builder/.cache/Homebrew/zstd_bottle_manifest--1.5.2-3... (7.2KB)
Removing: /home/builder/.cache/Homebrew/gmp_bottle_manifest--6.2.1_1... (7.4KB)
Removing: /home/builder/.cache/Homebrew/libmpc_bottle_manifest--1.2.1... (8.6KB)
Removing: /home/builder/.cache/Homebrew/go_bottle_manifest--1.19.1... (7.6KB)
Removing: /home/builder/.cache/Homebrew/Logs/glibc... (2 files, 4.2KB)
Removing: /home/builder/.cache/Homebrew/Logs/cf2... (2 files, 71.3KB)
Removing: /home/builder/.cache/Homebrew/Logs/kn... (4KB)
Removing: /home/builder/.cache/Homebrew/Logs/quickstart... (4KB)
Pruned 2 symbolic links from /home/linuxbrew/.linuxbrew
==> Caveats
==> hugo
Bash completion has been installed to:
/home/linuxbrew/.linuxbrew/etc/bash_completion.d
==> k9s
Bash completion has been installed to:
/home/linuxbrew/.linuxbrew/etc/bash_completion.d
Now we can launch hugo
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ hugo server
Start building sites …
hugo v0.110.0+extended linux/amd64 BuildDate=unknown
| EN
-------------------+-----
Pages | 7
Paginator pages | 0
Non-page files | 0
Static files | 7
Processed images | 0
Aliases | 1
Sitemaps | 1
Cleaned | 0
Built in 160 ms
Watching for changes in /home/builder/Workspaces/hugoBlog/myBlog/{archetypes,content,data,layouts,static,themes}
Watching for config changes in /home/builder/Workspaces/hugoBlog/myBlog/config.toml, /home/builder/Workspaces/hugoBlog/myBlog/themes/terminal/config.toml
Environment: "development"
Serving pages from memory
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop
Contentful
I’ll now add contentful-hugo
to pull in Contentful content
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ npm install contentful-hugo
added 131 packages, and audited 132 packages in 13s
16 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
npm notice
npm notice New major version of npm available! 8.5.1 -> 9.4.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.4.1
npm notice Run npm install -g npm@9.4.1 to update!
npm notice
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ node_modules/.bin/contentful-hugo –init checking for config… creating ./contentful-hugo.config.js config file created
adding shortcodes for rich text… created ./layouts/shortcodes/contentful-hugo/asset-hyperlink.html created ./layouts/shortcodes/contentful-hugo/embedded-asset.html created ./layouts/shortcodes/contentful-hugo/embedded-entry.html created ./layouts/shortcodes/contentful-hugo/entry-hyperlink.html created ./layouts/shortcodes/contentful-hugo/inline-entry.html
export CONTENTFUL_SPACE=”ukkohuhcdmei” export CONTENTFUL_TOKEN=”zu-_NRcOoZoflWogcgGcEQpgkRpEE5wlxGqCIc0Lj3M” export CONTENTFUL_PREVIEW_TOKEN=”7I_NI-xL9CRbdGjmUiviVUjjx5HsgA5H7QE6ZzShMOs”
Now we can pull in our pageBlogPosts
// go to https://github.com/ModiiMedia/contentful-hugo#configuration for configuration instructions
/**
* @type {import('contentful-hugo').ContentfulHugoConfig}
*/
module.exports = {
locales: [], // uses default locale if left empty
singleTypes: [],
repeatableTypes: [
{
id: 'pageBlogPost',
directory: 'content/posts',
mainContent: 'content',
resolveEntries: {
categories: 'fields.slug',
author: 'fields.name',
relatedPosts: 'sys.id',
},
},
],
};
This will work as we set our Environment Variables.
However, we could embed the values as well
module.exports = {
// fetches from default locale if left blank
locales: ['en-US', 'fr-FR'],
contentful: {
// defaults to CONTENTFUL_SPACE env variable
space: 'space-id',
// defaults to CONTENTFUL_TOKEN env variable
token: 'content-deliver-token',
// defaults to CONTENTFUL_PREVIEW_TOKEN env variable
previewToken: 'content-preview-token',
// defaults to "master"
environment: 'master',
},
Now when we run it
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ npm run dev
> dev
> contentful-hugo --preview && hugo server
---------------------------------------------
Pulling Preview Data from Contentful...
---------------------------------------------
pageBlogPost - 8 items
---------------------------------------------
Start building sites …
hugo v0.110.0+extended linux/amd64 BuildDate=unknown
| EN
-------------------+-----
Pages | 17
Paginator pages | 0
Non-page files | 0
Static files | 7
Processed images | 0
Aliases | 2
Sitemaps | 1
Cleaned | 0
Built in 106 ms
Watching for changes in /home/builder/Workspaces/hugoBlog/myBlog/{archetypes,content,data,layouts,package.json,static,themes}
Watching for config changes in /home/builder/Workspaces/hugoBlog/myBlog/config.toml, /home/builder/Workspaces/hugoBlog/myBlog/themes/terminal/config.toml
Environment: "development"
Serving pages from memory
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop
And we can view individual posts
CICD
Let’s first create a Github repo we can use to host the code
In my Settings, I’ll add secrets for the Contentful environment.
As a reminder, we see those in “API Keys” in Settings on Contentful
If you have more than one space, you can use the ones tied to “Blog”
I now have secrets for the Space, Delivery and Preview Tokens
I’ll make a .gitignore
file
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ cat .gitignore
# Created by https://www.toptal.com/developers/gitignore/api/hugo,linux,visualstudiocode,nodejs
# Edit at https://www.toptal.com/developers/gitignore?templates=hugo,linux,visualstudiocode,nodejs
### Hugo ###
# Generated files by hugo
/public/
/resources/_gen/
/assets/jsconfig.json
hugo_stats.json
# Executable may be added to repository
hugo.exe
hugo.darwin
hugo.linux
# Temporary lock file while building
/.hugo_build.lock
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
#!! ERROR: nodejs is undefined. Use list command to see defined gitignore types !!#
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
themes/
# End of https://www.toptal.com/developers/gitignore/api/hugo,linux,visualstudiocode,nodejs
Then add and push my existing repo up
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ git remote add origin https://github.com/idjohnson/myNewBlog.git
builder@DESKTOP-72D2D9T:~/Workspaces/hugoBlog/myBlog$ git push -u origin main
Enumerating objects: 29, done.
Counting objects: 100% (29/29), done.
Delta compression using up to 4 threads
Compressing objects: 100% (24/24), done.
Writing objects: 100% (29/29), 41.63 KiB | 4.16 MiB/s, done.
Total 29 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), done.
To https://github.com/idjohnson/myNewBlog.git
* [new branch] main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.
Now that I have some content in my repo
I’ll create the Github Actions build that will drive static site creation
There are a few ways we can add Hugo
to the Github Actions Runner. Using apt install
will get us the same old binary as before, so we don’t want to use that route.
You can use homebrew to easily add it:
- name: Install Hugo
run: |
umask 0002
test -d ~/.linuxbrew && eval "$(~/.linuxbrew/bin/brew shellenv)"
test -d /home/linuxbrew/.linuxbrew && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
test -r ~/.bash_profile && echo "eval \"\$($(brew --prefix)/bin/brew shellenv)\"" >> ~/.bash_profile
echo "eval \"\$($(brew --prefix)/bin/brew shellenv)\"" >> ~/.profile
brew install hugo
Or a Debian package, which will pin it to a specific release
- name: Install Hugo
run: |
umask 0002
sudo apt-get update -y
wget https://github.com/gohugoio/hugo/releases/download/v0.79.0/hugo_0.79.0_Linux-64bit.deb
sudo dpkg -i hugo_0.79.0_Linux-64bit.deb
I used both, but stuck with the latter. My first shot at generating looked as such
$ cat .github/workflows/generate-site.yml
jobs:
build_deploy_test:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v2
- name: Install Hugo
run: |
umask 0002
sudo apt-get update -y
wget https://github.com/gohugoio/hugo/releases/download/v0.79.0/hugo_0.79.0_Linux-64bit.deb
sudo dpkg -i hugo_0.79.0_Linux-64bit.deb
sudo apt-get install -y tree
- name: Hugo Build
run: |
npm install
npm run build
tree .
env: # Contentful Tokens
CONTENTFUL_SPACE: $
CONTENTFUL_TOKEN: $
CONTENTFUL_PREVIEW_TOKEN: $
We can see in our build output the results of the tree
command that lists our directory. We can see it built out the markdown for our Contentful posts
Azure Static Web App
The Static Web App (or Site), is a way we can host this generated content in Azure for low to no cost.
I’ll go to the Azure Portal and “+ Add a Resource” and search for “Static Web App”
and click “Create”
I’ll create a fresh Resource Group
Then give it a name and select (if not selected already) the Free tier. I’ll then want to click “Sign in with GitHub”
And grant access to my account (and possibly org)
I can now select the Organization
In the “Build Presets”, I’ll select “Hugo”
When I click “Preview workflow file”, I can now see some example code we can use
I’ll set that aside and click “Review and Create” then lastly, “Create” to create the Static Site
When that was created, it updated our Github repo for us automatically. We can now see a new flow in the system
Not suprisingly, that errored because it is really designed for a basic Hugo setup, not a Contentful driven one
I’ll use git pull
locally to bring in the new file
builder@DESKTOP-QADGF36:~/Workspaces/myNewBlog$ git pull
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 5 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (5/5), 1.16 KiB | 1.16 MiB/s, done.
From https://github.com/idjohnson/myNewBlog
18b50a8..5b251ef main -> origin/main
Updating 18b50a8..5b251ef
Fast-forward
.github/workflows/azure-static-web-apps-purple-bush-00ab46010.yml | 45 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 .github/workflows/azure-static-web-apps-purple-bush-00ab46010.yml
The key change is to add the CONTENTFUL secrets
While we test the new flow, I’ll disable the former (just so we don’t waste time doing double builds)
We can see our change of adding the env secrets sorted out the static website build
At the bottom of the log, we can see our URL; https://purple-bush-00ab46010.2.azurestaticapps.net
I can see one issue right out, that is the Domain needs to be adjusted
That is set in the ‘baseURL’ of config.toml
$ cat config.toml
baseURL = "https://purple-bush-00ab46010.2.azurestaticapps.net/"
languageCode = "en-us"
title = "My New Hugo Site"
theme = 'terminal'
Once, changed, our freshly built site looks correct
And we can view individual posts without issue
Azure Stats
We can view our usage back on the Azure Portal.
This includes metrics like Requests and Data egress
Say we wish to use a custom domain. Nothing wrong with an ‘azurestaticapps’ site, but it would be nice for something a bit shorter.
I’ll check to see if I have any active DNS zones in Azure already (and I do)
But for fun, let’s add a new one. We can see I registered a “tpk.life” domain for fun a few weeks ago in Gandi.
I’ll click add and put in the details
After creation, we can see the resource for the records we need to change in order to use the Hosted Zone in Azure DNS
In Gandi, I’ll just change from Gandi’s DNS to Azure
Then save
This can take up to 24h to update. That said, I can use the one (tpk.pw) that has already been validated for some time
We’ll go back to the Static Web App, in Settings/Custom domains and choose to “+ Add” a “Custom domain on Azure DNS”
I’ll give it a name
Then click “Add”
While it seems to have gone out to lunch on the Azure Portal UI, I can already see the change reflected on the site
I’ll change my URL in the config and push a commit
builder@DESKTOP-QADGF36:~/Workspaces/myNewBlog$ git diff config.toml
diff --git a/config.toml b/config.toml
index ba4fff6..bb0425f 100644
--- a/config.toml
+++ b/config.toml
@@ -1,4 +1,4 @@
-baseURL = "https://purple-bush-00ab46010.2.azurestaticapps.net/"
+baseURL = "https://newblog.tpk.pw/"
languageCode = "en-us"
title = "My New Hugo Site"
theme = 'terminal'
builder@DESKTOP-QADGF36:~/Workspaces/myNewBlog$ git add config.toml
builder@DESKTOP-QADGF36:~/Workspaces/myNewBlog$ git commit -m "change to new URL"
[main 34e59c6] change to new URL
1 file changed, 1 insertion(+), 1 deletion(-)
builder@DESKTOP-QADGF36:~/Workspaces/myNewBlog$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 16 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 368 bytes | 368.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/idjohnson/myNewBlog.git
da6c401..34e59c6 main -> main
One the Workflow completed, I can see the proper URLs in the site
Triggering from Contentful
To trigger a Workflow externally, in Github we’ll need to add a “dispatch”.
We can add a trigger for dispatches then a specific type (webhook) in our Github Workflow YAML
name: Azure Static Web Apps CI/CD
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- main
workflow_dispatch:
repository_dispatch:
types:
- webhook
jobs:
In Contentful, to use the Dispatch webhook, We first go to Settings / Webhooks
Oddly they have every CI except Github listed in the Templates
I’ll choose “Add Webhook”
I add a URL that adds “/dispatches” to the Github URL, then a custom header for “Accept” set to “application/vnd.github+json”.
For the “+ Secret header”, I’ll want to add a Key of “Authorization” and value of “Bearer {personal token with repo access}”
Something like ‘Bearer ghp_AE5asdfE4Asadf54AEasdf545AasdfE’
Lastly, because we specified a type (webhook), we’ll want to add that in the payload
The resulting Webhook definition should look similar to this. (see below, we end up tweaking this in the end)
Right now, I have it set to “All Events”. But arguably, we could trim it to just Entry changes
Once saves, we can see it listed as “Active”
Triggering the Workflow
Let’s add a quick blog entry
I won’t make it too fancy, just a simple Hello World will do
I’ll click “Publish” which will change the status
However, my webhook failed
It took a while, the REST API had changed over time and the guide I followed was not up to date.
The corrected webhook used “Bearer” not “token” in the Authorization and whole different URL:
"https://api.github.com/repos/{ org or owner }/{ repo name }/actions/workflows/{ workflow name or id }/dispatches"
e.g.
"https://api.github.com/repos/idjohnson/myNewBlog/actions/workflows/azure-static-web-apps-purple-bush-00ab46010.yml/dispatches"
Thus, the full definition of the resulting (successful) webhook looked like:
which triggered successfully from Contentful
and queued in Github
The problem, I found was that template as deployed by Azure only allowed PRs and Push events. We need to update it to allow workflow_dispatch as well:
jobs:
build_and_deploy_job:
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
name: Build and Deploy Job
We can now watch the full workflow in action (however, I clearly need to limit the steps to just publish actions as you’ll see)
Limitting the events
I decided I should attempt to clean up the events triggering GH. I reduced it to pubish/unpublish on Content Types and Entrys.
We can see that in action below
Automated Reports
We can setup a “Task” in the Static site to send us reports. Select Tasks under Automation
Add a task
Here we’ll use the only template presently available for monthly reports
I can use ARM or O365 for authentication. (actually i needed to go back and setup both)
I’ll set a destination
It does not that it’s billable, which means the background Azure Logic App will probably cost a small amount to run.
We can see that is what it intends to make on the Review and Create page
I now see a scheduled task listed
Summary
I should note that before I realized the Icon was a Gopher, I figured it to be a Hamster. Thus, I had a bit of art that I think is too cute to not share:
Let’s review what we covered today. We created a new Github Repository and a new NodeJS project. We setup Hugo locally and created the contentful-hugo connection using some environment variables as the contentful-hugo node module. After testing, we setup a Github Workflow to build our project then tied it to a new Azure Static Web App site. There we added a custom domain though an Azure DNS hosted zone. Lastly, we worked out the Github “dispatcher” webhook trigger and tied it to Contentful to deploy on Contentful events.
Provided we keep the workspace under 500Mb and are happy with 2 domains an App, we’ll live just dandy in the free tier.
Thus far, my costs have stayed at US$0 in Azure