Hugo Assets Pipeline on GitHub Pages (Actions + gh-pages)
Deploy fingerprinted assets, submodules, and custom domains with GitHub Actions. Fix MIME and path errors.
Tested on: Hugo 0.139.4-extended, GitHub Actions, user site username.github.io/repo/
Problem: CSS/JS 404, wrong MIME type, baseURL broke asset paths.
baseURL for project pages
Repo: github.com/user/myblog → served at https://user.github.io/myblog/
hugo.toml:
baseURL = "https://user.github.io/myblog/"
canonifyURLs = true
relativeURLs = false
Never use relativeURLs = true with fingerprinted assets — hashes break on nested pages.
GitHub Actions workflow
.github/workflows/hugo.yml:
name: Deploy Hugo
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- uses: actions/configure-pages@v5
- uses: peaceiris/actions-hugo@v3
with:
hugo-version: '0.139.4'
extended: true
- run: hugo --gc --minify
- uses: actions/upload-pages-artifact@v3
with:
path: public
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
Enable Pages: Settings → Pages → Source: GitHub Actions.
Fingerprinted assets
layouts/partials/head.html:
{{ $css := resources.Match "css/**/*.css" | resources.Concat "bundle.css" | minify | fingerprint }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}" crossorigin="anonymous">
Output: /myblog/assets/css/bundle.abc123.css — works with project baseURL.
Error: assets 404
GET https://user.github.io/assets/css/bundle.css 404
Missing /myblog/ prefix — baseURL was https://user.github.io/ instead of project path.
Error: text/plain MIME
Refused to apply style because MIME type is 'text/plain'
Usually means 404 HTML returned for CSS URL. Fix path, not MIME config.
Custom domain on project repo
baseURL = "https://www.myblog.com/"
Add static/CNAME:
www.myblog.com
DNS: CNAME www → user.github.io.
Verify
hugo --minify
grep -o 'href="[^"]*css[^"]*"' public/index.html
# all URLs should start with /myblog/ or full domain
npx http-server public -p 8080
# test nested page assets
After deploy:
curl -I https://user.github.io/myblog/assets/css/bundle.*.css
# HTTP/2 200, content-type: text/css
Submodule gotcha
submodules: recursive
Without it, theme missing → 12KB unstyled HTML.
Result
812-post site deploys in 48s. Asset cache hit rate 99% on repeat visitors via fingerprint + long cache.