Hugo Build Wrapper¶
The headline rule: never run bare hugo commands. Always use the wrapper.
# Build
pwsh C:\ssClawy\aguidetocloud-revamp\scripts\hugo-safe.ps1
# Minified build
pwsh C:\ssClawy\aguidetocloud-revamp\scripts\hugo-safe.ps1 --minify
# Dev server
pwsh C:\ssClawy\aguidetocloud-revamp\scripts\hugo-safe.ps1 server --port 1314 --noHTTPCache
Why the wrapper exists¶
Bare hugo has three failure modes that the wrapper handles:
| Failure | What you'd see | What the wrapper does |
|---|---|---|
| Zombie Hugo process holding a port | error: address already in use or silent server hang |
Kills any hugo.exe process before starting |
Stale lock file in resources/_gen/ |
error: failed to lock resource |
Removes the lock file before building |
| Multiple concurrent builds clobbering output | Random files missing from public/ |
Serializes — one build at a time |
It also normalises arg passing so you don't get bitten by PowerShell's quoting rules.
What "normal" looks like¶
A clean build of aguidetocloud-revamp (1,774 pages):
- Build time: ~100 seconds. Don't panic if it's not 5s.
- Pagefind step: runs after Hugo via
npx pagefind@latest --site public. Adds another ~15s. - Output: ~13,000 files in
public/. - Memory: spikes to ~1.5GB during page generation. Normal.
If a build takes <30s, something probably skipped (Hugo's incremental cache hit). Re-run with --cleanDestinationDir to force full rebuild.
Concurrent builds — only ONE at a time¶
Across all sessions, on all devices. The wrapper enforces this within one machine, but a different session on a different machine can still race. Coordinate manually if working roaming.
If you start a build in Session A and need Hugo in Session B, wait. Don't kill A's build.
--noHTTPCache for the dev server¶
Hugo's dev server caches HTTP responses aggressively. After CSS or JS changes, you'll see the old version unless you pass --noHTTPCache.
You'll also need to manually restart the dev server when template files change — Hugo's "Fast Render" misses template-only changes.
When the lock file persists¶
Sometimes the wrapper's auto-clean doesn't catch a lock file (e.g. Windows file lock from a still-open editor). Manual recovery:
cd C:\ssClawy\aguidetocloud-revamp
Remove-Item -Recurse -Force resources\_gen\
Remove-Item -Force resources\.hugo_build.lock
Then re-run the wrapper.
When the build silently produces wrong output¶
Symptom: git diff on public/ shows nothing changed even though you edited templates.
Cause: incremental cache hit on stale state.
Fix:
Deploy, not just build¶
Hugo build is local. The actual deploy is Cloudflare Pages auto-build on push. So the local Hugo build's job is verification only — confirm the build would succeed before you push. The CF Pages build is what users actually see.
This means: a successful local build is necessary but not sufficient. The deploy can still fail if:
- A plugin needs a different Node version
- A CF env var is missing
- An OG image generation step fails
- Pagefind binary changes between local and CF
That's why Deployment Playbook step 7 is "Playwright test against the deployed site after push", not just "build succeeded".
Cross-references¶
- Deployment Playbook — step 2
~/.copilot/copilot-instructions.md§ Hugo Build — the rule