Yesterday I spent 30 minutes debugging a Hugo site that showed unstyled pages despite correct templates and CSS. The solution? A clean rebuild. Here’s why Hugo’s live reload sometimes lies to you and how to fix it.
The Problem
Built a new page in Hugo. Template exists. CSS loads. But the page renders as plain HTML with no styling.
# Server shows no errors
hugo server
# "Serving pages from disk"
# "Web Server is available at http://localhost:1313/"
# Browser shows broken page
curl http://localhost:1313/new-page/
# Plain HTML, no wrapper, no CSS classes
Template file exists:
ls themes/custom/layouts/section/new-page.html
# File exists ✓
CSS file loads:
curl http://localhost:1313/css/style.css
# Returns full CSS ✓
But the page doesn’t use the template.
Why This Happens
Hugo’s live reload (hugo server) keeps files in memory for speed. When you:
- Add a new section (e.g.,
/content/apply/) - Create a new layout (e.g.,
layouts/section/apply.html) - The server doesn’t always pick up the new template
Hugo serves from memory → Old (empty) template → Unstyled HTML
Refreshing the browser doesn’t help. The issue is server-side, not client-side.
The Fix: Clean Rebuild
Kill the server and rebuild from scratch:
# 1. Stop hugo server (Ctrl+C)
# 2. Delete cached files
rm -rf public resources .hugo_build.lock
# 3. Build fresh
hugo --minify
# 4. Start server without caching
hugo server --bind 0.0.0.0 --port 1313 \
--noHTTPCache \
--disableFastRender
Why each flag matters:
rm -rf public→ Removes built siterm -rf resources→ Clears processed images, CSS, JSrm -rf .hugo_build.lock→ Clears build lock filehugo --minify→ Builds fresh (verifies no build errors)--noHTTPCache→ Disables HTTP caching--disableFastRender→ Forces full render on every change
After this, the page renders correctly.
When Clean Rebuilds Are Needed
Symptom 1: New page shows unstyled HTML
- Template exists but isn’t applied
- CSS loads but classes don’t style
Symptom 2: Changes don’t appear
- Edit template
- Reload browser
- Still shows old version
Symptom 3: “Template not found” warnings disappear but page still broken
- Hugo logs show warnings initially
- You fix the template
- Warnings gone but page still wrong
Symptom 4: Raw HTML shows instead of rendered content
- Markdown renders as HTML
- You enable
unsafe = truein config - Content still shows as raw HTML
The Nuclear Option Script
Save this as rebuild.sh in your Hugo project:
#!/bin/bash
# Hugo clean rebuild script
echo "🧹 Cleaning build artifacts..."
rm -rf public resources .hugo_build.lock
echo "🔨 Building site..."
hugo --minify
if [ $? -eq 0 ]; then
echo "✅ Build successful"
echo "🚀 Starting server..."
hugo server --bind 0.0.0.0 --port 1313 \
--noHTTPCache \
--disableFastRender
else
echo "❌ Build failed"
exit 1
fi
Make it executable:
chmod +x rebuild.sh
Run it whenever Hugo misbehaves:
./rebuild.sh
Why Hugo Does This
Hugo optimizes for speed. Live reload keeps processed files in memory to avoid re-reading the filesystem on every change.
Trade-off:
- Fast: Changes render in milliseconds
- Fragile: Cache doesn’t always invalidate correctly
When cache invalidation fails:
- New sections
- New layouts
- Config changes
- Raw HTML enable/disable
The cache doesn’t detect these changes reliably.
Prevention Tips
1. Structure your site up front
Create all main sections before building templates:
content/
├── about/
├── services/
├── blog/
└── contact/
Hugo caches section structure. Adding sections mid-development breaks the cache.
2. Restart server after config changes
Any change to hugo.toml or config.toml requires a restart:
# Don't just save the file
# Stop server (Ctrl+C) and restart
hugo server
3. Use --disableFastRender during development
Fast render is great for content changes (markdown). It’s bad for structure changes (templates, sections).
Development:
hugo server --disableFastRender
Content editing:
hugo server # Fast render enabled
4. Check public/ directory
Hugo builds to public/. If the file looks wrong there, it’s a build issue (not a server cache issue).
cat public/new-page/index.html
If it’s wrong in public/, clean rebuild. If it’s right in public/ but wrong in browser, clear browser cache.
Other Common Hugo Template Issues
Issue: “Template not found”
Symptom:
WARN found no layout file for "html" for kind "section"
Cause: Hugo’s template lookup is strict. Section pages need specific template names.
Fix: Use correct template path:
- Section index:
layouts/section/NAME.htmlorlayouts/_default/list.html - Single page:
layouts/_default/single.html
Issue: Raw HTML stripped
Symptom: HTML in markdown doesn’t render.
Cause: Goldmark (Hugo’s markdown parser) blocks raw HTML by default.
Fix: Enable unsafe mode:
# hugo.toml
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
Then clean rebuild.
Issue: Partial not found
Symptom:
Error: failed to render pages: template not found
Cause: Partial path is wrong.
Fix: Partials need exact path from layouts/partials/:
<!-- Wrong -->
{{ partial "header" . }}
<!-- Right -->
{{ partial "partials/header.html" . }}
The Lesson
Hugo is fast and simple, but its caching is aggressive. When things look wrong:
- Check logs first (warnings reveal template issues)
- If no warnings but still broken: clean rebuild
- Don’t trust live reload for structure changes
The nuclear option (delete everything, rebuild fresh) fixes 90% of weird Hugo bugs.
The Bottom Line
Hugo’s live reload is great for:
- Content changes (markdown files)
- CSS tweaks
- Minor template edits
Hugo’s live reload breaks on:
- New sections
- New layouts
- Config changes
- Major template restructuring
Solution: Clean rebuild script. Run it liberally during development. The 10 seconds it takes beats 30 minutes of debugging.
Debugging stack: Hugo 0.159, macOS, Chrome DevTools