Wrap EVERYTHING in NPM!
So, node
and npm
seem to be all the rage these days, and perhaps for good reason. I recently fell in love with Eleventy/11ty over Hugo because it’s Javascript, not Go, and it’s elegantly simple with tons of flexibility. I recently tried to add Pagefind search to a Hugo static web site (see https://static.grinnell.edu/dlad-blog/posts/143-significant-rootstalk-retooling/). If Rootstalk, an Azure Static Web App was framed in node.js
, as both Eleventy and Pagefind are, there would be no problem. The Azure scripts used to deploy those frameworks are far more customizable than Hugo, and there’s documentation to prove it.
So, how might I approach combining Hugo with Pagefind in the cloud? Well, A Powerful Blog Setup with Hugo and NPM* by Tom Hombergs looked like a promising place to start. The process that Tom advocates leverages a neat little package called hugo-bin.
*The links provided above and below are to a Wayback Machine capture of the original post.
That Was Too Easy!
Wrapping my Hugo site in an NPM package was so easy that I forgot to document it… and maybe I really didn’t need too. Time to catch up, so here’s a brief sysnopsis of what I did…
Following Tom’s Excellent Advice
I started by studying A Powerful Blog Setup with Hugo and NPM and quickly found that I could easily follow it almost verbatim. Since I already had npm
and Hugo
installed I skipped ahead to the section titled “Setting Up a Hugo Project” and then to the npx
and git
commands there. My experience, mostly in commands, looked like this on my Mac Mini workstation.
cd ~/GitHub/
# Named the new project npm-rootstalk so it would not confilct with any of my existing `rootstalk...` directories
mkdir npm-rootstalk
cd npm-rootstalk
npx hugo new site . --force
# Copied the contents of my old project into the new one and then removed whatever I no longer needed
cp -fr ~/GitHub/rootstalk/. .
# Installed Pagefind...
npm install pagefind
git init
# I created a new empty repo in GitHub called npm-rootstalk, then...
git remote add origin https://github.com/Digital-Grinnell/npm-rootstalk
git add .
git commit -m "Initial commit of new npm-wrapped Hugo project"
git push
Having secured a new repo I moved to running Hugo locally, then polishing my package.json
scripts as Tom did. I now have a package.json
that reads like this:
{
"name": "npm-rootstalk",
"version": "1.0.0",
"description": "Rootstalk website built with Hugo and the Lightbi theme inside an NPM package. May 2023.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "npm run hugo:build && npx pagefind --source public",
"do:build": "hugo -d public && npx pagefind --source public",
"azure:build": "hugo -d public --baseURL=\"https://yellow-wave-0e513e510.3.azurestaticapps.net/\" && npx pagefind --source public",
"clean": "npm run hugo:clean",
"serve": "npm run hugo:build && npx pagefind --source public --bundle-dir ../static/_pagefind && npm run hugo:serve",
"hugo:build": "hugo -d public",
"hugo:serve": "hugo server",
"hugo:clean": "rm -rf build resources public"
},
"author": "Mark A. McFate",
"license": "ISC",
"dependencies": {
"hugo-bin": "^0.102.0",
"pagefind": "^0.12.0"
}
}
It Works!
Now I just use npm run serve
to build the Hugo site, index it with Pagefind, and serve it locally at http://localhost:1313.
A Staging Site in Azure
I can simply push changes to the main
branch of the npm-rootstalk
repo to trigger an Azure (aka GitHub Actions) rebuild, indexing and deployment of the site to this address.
A New Production Branch
Pushing to production is just as simple, I just have to push changes to the new production
branch of the code and my app spec at DigitalOcean (see below) takes care of building, indexing, and deploying to https://rootstalk.grinnell.edu.
That DO app spec reads like this:
alerts:
- rule: DEPLOYMENT_FAILED
- rule: DOMAIN_FAILED
domains:
- domain: rootstalk.grinnell.edu
type: PRIMARY
- domain: prairiejournal.grinnell.edu
type: ALIAS
envs:
- key: TZ
scope: RUN_AND_BUILD_TIME
value: America/Chicago
- key: HUGO_MATOMO_ID
scope: RUN_AND_BUILD_TIME
value: "15"
ingress:
rules:
- component:
name: npm-rootstalk
match:
path:
prefix: /
name: npm-rootstalk
region: nyc
static_sites:
- build_command: npm run build
environment_slug: node-js
github:
branch: production
deploy_on_push: true
repo: Digital-Grinnell/npm-rootstalk
name: npm-rootstalk
source_dir: /
It’s heavenly! And that’s all for now.