Local development
Quick start
# Clone with submodules (theme is a submodule)
git clone --recurse-submodules https://github.com/NickelFace/maks.top.git
cd maks.top
# Switch to working branch
git checkout hugo
Running the dev server
Three options depending on what you need:
# Option 1 โ full cycle (like CI): build + index + serve
./dev.sh
# = hugo && npx pagefind --site public && hugo server --disableFastRender
# Option 2 โ fast iteration (no Pagefind, search won't work)
hugo server -D
# Option 3 โ different port if 1313 is busy
hugo server -D --port 1314
--disableFastRenderforces Hugo to rebuild the full page on each change instead of patching only the changed part. Slower, but prevents stale state in the browser.
-Dincludes draft pages (draft: truein frontmatter). Without it, drafts are skipped.
Why run Pagefind locally?
hugo server serves from memory โ public/ is not written to disk. But Pagefind needs the built HTML files. That’s why dev.sh first runs hugo (writes to public/), indexes it with Pagefind, then starts the server with --disableFastRender.
Without this step the search box on /posts/ returns no results locally.
Checking for CSS issues
Browser cache often masks CSS changes during local development:
# Always verify CSS changes in:
# โ Incognito window, or
# โ DevTools โ Network tab โ check "Disable cache" โ reload
CI/CD pipeline
Deploys automatically on every push to the hugo branch.
git push origin hugo
โ
โผ
GitHub Actions (.github/workflows/deploy.yml)
โ
โโโ 1. actions/checkout@v4
โ submodules: recursive โ required! theme is a submodule
โ fetch-depth: 0 โ full history for .GitInfo
โ
โโโ 2. peaceiris/actions-hugo@v3
โ hugo-version: "latest"
โ extended: true โ required for SASS support
โ
โโโ 3. hugo --minify --gc
โ --minify compresses HTML/CSS/JS
โ --gc removes unused cache files
โ
โโโ 4. grep stylesheet check โ debug step, verifies CSS paths in public/index.html
โ
โโโ 5. pagefind --site public โ builds search index into public/pagefind/
โ
โโโ 6. actions/upload-pages-artifact@v3
โ
โโโ 7. actions/deploy-pages@v4
โ
โผ
https://maks.top/
Branch setup
| Branch | Purpose |
|---|---|
hugo | Working branch โ all commits go here, CI runs from here |
main | Unused / legacy |
gh-pages | Auto-created by GitHub Actions, do not touch |
Never push directly to
gh-pagesโ it’s overwritten on every deploy.
Why submodules: recursive is required
The theme themes/maks/ is a git submodule. Without submodules: recursive in checkout, Hugo finds an empty themes/maks/ directory and fails with:
Error: module "maks" not found; ...
GitHub Pages setup (one-time)
- Settings โ Pages โ Source: GitHub Actions (not “Deploy from branch”)
- Add custom domain:
maks.top - GitHub auto-issues Let’s Encrypt TLS and serves via Fastly CDN
DNS records at Cloudflare:
| Type | Name | Value |
|---|---|---|
| A | @ | 185.199.108.153 |
| A | @ | 185.199.109.153 |
| A | @ | 185.199.110.153 |
| A | @ | 185.199.111.153 |
| CNAME | www | nickelface.github.io |
Known deployment pitfalls
actions/configure-pages@v4 โ do not use
This action is commonly seen in Hugo deployment examples but must not be used here.
Why it breaks things: configure-pages@v4 reads the GitHub Pages URL and overwrites baseURL in the Hugo config. For a custom domain (maks.top) it sets the wrong value, which breaks all relative CSS/JS paths:
<!-- broken result: -->
<link rel="stylesheet" href="https://nickelface.github.io/styles/global.css">
<!-- correct result (without configure-pages): -->
<link rel="stylesheet" href="/styles/global.css">
The current deploy.yml does not include this step. Don’t add it.
hugo-version: "latest" may break on major updates
peaceiris/actions-hugo@v3 with hugo-version: "latest" always installs the newest version. If Hugo releases a breaking change, the build may fail unexpectedly.
Fix if this happens: pin to a specific version:
- uses: peaceiris/actions-hugo@v3
with:
hugo-version: "0.145.0" # pin to last known good version
extended: true
public/ edited manually
public/ is fully regenerated on every hugo run. Any manual changes are overwritten.
Never edit files in public/ directly.
Theme submodule not updated
If themes/maks/ shows as an empty directory locally:
# Initialize and pull submodule
git submodule update --init --recursive
If the submodule is behind:
cd themes/maks
git pull origin main
cd ../..
git add themes/maks
git commit -m "chore: update theme submodule"
markup.goldmark.renderer.unsafe = false
Raw HTML and <script> tags in Markdown files are silently stripped unless unsafe = true is set in hugo.toml. This is already configured correctly, but if you ever reset the config โ make sure it stays:
[markup.goldmark.renderer]
unsafe = true
Checking a failed build
GitHub Actions logs are the primary source. Common failure points:
# 1. Hugo build failed โ check for template errors
# Look for: "Error: ... template"
# 2. Pagefind failed โ check npm/node availability
# Look for: "pagefind: command not found"
# 3. Deploy failed โ check Pages permissions
# Look for: "HttpError: Not Found" or permissions errors
# Fix: Settings โ Pages โ Source must be "GitHub Actions"
The debug step in deploy.yml prints CSS link tags from public/index.html โ useful for confirming that CSS paths are correct after a build:
- name: Check generated HTML
run: grep -r "stylesheet" public/index.html | head -20