Loading...
Loading...
This skill provides comprehensive knowledge for building static websites with Hugo static site generator. It should be used when setting up Hugo projects (blogs, documentation sites, landing pages, portfolios), integrating Tailwind CSS v4 for custom styling, integrating headless CMS systems (Sveltia CMS or TinaCMS), deploying to Cloudflare Workers with Static Assets, configuring themes and templates, and preventing common Hugo setup errors. Use this skill when encountering these scenarios: scaffolding new Hugo sites, choosing between Hugo Extended and Standard editions, integrating Tailwind CSS v4 with Hugo Pipes, configuring hugo.yaml or hugo.toml files, integrating PaperMod or other themes via Git submodules, setting up Sveltia CMS or TinaCMS for content management, deploying to Cloudflare Workers or Pages, troubleshooting baseURL configuration, resolving theme installation errors, fixing frontmatter format issues (YAML vs TOML), preventing date-related build failures, setting up PostCSS with Hugo, or setting up CI/CD with GitHub Actions. Keywords: hugo, hugo-extended, static-site-generator, ssg, go-templates, papermod, goldmark, markdown, blog, documentation, docs-site, landing-page, sveltia-cms, tina-cms, headless-cms, cloudflare-workers, workers-static-assets, wrangler, hugo-server, hugo-build, frontmatter, yaml-frontmatter, toml-config, hugo-themes, hugo-modules, multilingual, i18n, github-actions, version-mismatch, baseurl-error, theme-not-found, tailwind, tailwind-v4, tailwind-css, hugo-pipes, postcss, css-framework, utility-css, hugo-tailwind, tailwind-integration, hugo-assets
npx skill4agent add jackspace/claudeskillz hugo# macOS
brew install hugo
# Linux (Ubuntu/Debian)
wget https://github.com/gohugoio/hugo/releases/download/v0.152.2/hugo_extended_0.152.2_linux-amd64.deb
sudo dpkg -i hugo_extended_0.152.2_linux-amd64.deb
# Verify Extended edition
hugo version # Should show "+extended"# Use YAML format (not TOML) for better CMS compatibility
hugo new site my-blog --format yaml
# Initialize Git
cd my-blog
git init
# Add PaperMod theme (recommended for blogs)
git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod--format yaml--recursive# hugo.yaml - Minimal working configuration
baseURL: "https://example.com/"
title: "My Hugo Blog"
theme: "PaperMod"
languageCode: "en-us"
enableRobotsTXT: true
params:
ShowReadingTime: true
ShowShareButtons: true
defaultTheme: auto # Supports dark/light/auto# Create first post
hugo new content posts/first-post.md
# Run development server (with live reload)
hugo server
# Build for production
hugo --minify
# Output is in public/ directorybrew install hugo# Check latest version: https://github.com/gohugoio/hugo/releases
VERSION="0.152.2"
wget https://github.com/gohugoio/hugo/releases/download/v${VERSION}/hugo_extended_${VERSION}_linux-amd64.deb
sudo dpkg -i hugo_extended_${VERSION}_linux-amd64.debdocker run --rm -it -v $(pwd):/src klakegg/hugo:ext-alpinenpm install -g hugo-binhugo version
# Should output: hugo v0.152.2+extended
# ^^^^^^^^ Must show "+extended"hugo new site my-site --format yaml
cd my-sitemy-site/
├── hugo.yaml # Configuration (YAML format)
├── archetypes/ # Content templates
│ └── default.md
├── content/ # All your content goes here
├── data/ # Data files (JSON/YAML/TOML)
├── layouts/ # Template overrides
├── static/ # Static assets (images, CSS, JS)
├── themes/ # Themes directory
└── public/ # Build output (generated, git ignore)--format yamlpublic/.gitignore# Popular themes:
# - PaperMod (blogs): https://github.com/adityatelange/hugo-PaperMod
# - Book (docs): https://github.com/alex-shpak/hugo-book
# - Academic (research): https://github.com/HugoBlox/theme-academic-cv
# - Ananke (general): https://github.com/theNewDynamic/gohugo-theme-ananke
git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperModhugo mod init github.com/username/my-site
# In hugo.yaml:
# module:
# imports:
# - path: github.com/adityatelange/hugo-PaperModtheme: "PaperMod"git clone --recursive https://github.com/username/my-site.git
# Or if already cloned:
git submodule update --init --recursive--depth=1git submodule update --init --recursivebaseURL: "https://example.com/"
title: "My Hugo Blog"
theme: "PaperMod"
languageCode: "en-us"
defaultContentLanguage: "en"
enableRobotsTXT: true
buildDrafts: false
buildFuture: false
buildExpired: false
enableEmoji: true
minify:
disableXML: true
minifyOutput: true
params:
env: production
title: "My Hugo Blog"
description: "A blog built with Hugo and PaperMod"
author: "Your Name"
ShowReadingTime: true
ShowShareButtons: true
ShowPostNavLinks: true
ShowBreadCrumbs: true
ShowCodeCopyButtons: true
defaultTheme: auto # dark, light, auto
socialIcons:
- name: twitter
url: "https://twitter.com/username"
- name: github
url: "https://github.com/username"
menu:
main:
- identifier: posts
name: Posts
url: /posts/
weight: 10
- identifier: about
name: About
url: /about/
weight: 20
outputs:
home:
- HTML
- RSS
- JSON # Required for searchhugo.yamlhugo.tomlhugo.jsonconfig/
├── _default/
│ └── hugo.yaml
├── production/
│ └── hugo.yaml # Overrides for production
└── development/
└── hugo.yaml # Overrides for local dev# Blog post
hugo new content posts/my-first-post.md
# Page
hugo new content about.md
# Nested documentation
hugo new content docs/getting-started/installation.md---
title: "My First Post"
date: 2025-11-04T10:00:00+11:00
draft: false
tags: ["hugo", "blog"]
categories: ["General"]
description: "A brief description for SEO"
cover:
image: "/images/cover.jpg"
alt: "Cover image"
---
# Post content starts here
This is my first Hugo blog post!+++
title = "My First Post"
date = 2025-11-04T10:00:00+11:00
draft = false
tags = ["hugo", "blog"]
+++---+++draft: falsedate--buildFuture# Start server
hugo server
# With drafts visible
hugo server --buildDrafts
# With future-dated posts
hugo server --buildFuture
# Bind to specific port
hugo server --port 1314
# Access at: http://localhost:1313# Basic build
hugo
# With minification (recommended)
hugo --minify
# With specific baseURL (for deployment)
hugo --minify --baseURL https://example.com
# Or use environment variable
hugo --minify -b $CF_PAGES_URLpublic/--minifypublic/{
"name": "my-hugo-site",
"compatibility_date": "2025-01-29",
"assets": {
"directory": "./public",
"html_handling": "auto-trailing-slash",
"not_found_handling": "404-page"
}
}# Build site
hugo --minify
# Deploy to Workers
npx wrangler deploy.github/workflows/deploy.ymlname: Deploy to Cloudflare Workers
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive # Important for theme submodules!
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.152.2'
extended: true
- name: Build
run: hugo --minify
- name: Deploy to Cloudflare Workers
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}assets.directory"./public"html_handling: "auto-trailing-slash"not_found_handling: "404-page"submodules: recursive--format yamlpublic/draft: false--recursive/images/photo.jpg../images/photo.jpghugo --minifypublic/submodules: recursive-b $CF_PAGES_URLresources/_gen/.hugo_build.lockError: SCSS support not enabledhugo version | grep extendedbaseURLconfig/production/hugo.yamlhugo -b $CF_PAGES_URL--format yamlhugo.yamlHUGO_VERSIONhugo-version: '0.152.2'---+++---+++Error: module "PaperMod" not foundthemetheme: "PaperMod"git submodule addgit submodule update --init --recursive--buildFuture--buildFuturedatepublic/public/public/.gitignorefailed to extract shortcodehugo mod cleanhugo mod tidybaseURL: "https://example.com/"
title: "My Hugo Blog"
theme: "PaperMod"
languageCode: "en-us"
defaultContentLanguage: "en"
enableRobotsTXT: true
buildDrafts: false
buildFuture: false
buildExpired: false
enableEmoji: true
pygmentsUseClasses: true
summaryLength: 30
minify:
disableXML: true
minifyOutput: true
params:
env: production
title: "My Hugo Blog"
description: "A blog built with Hugo and PaperMod"
keywords: [Blog, Hugo, Tech]
author: "Your Name"
images: ["/images/og-image.jpg"]
DateFormat: "January 2, 2006"
defaultTheme: auto # dark, light, auto
disableThemeToggle: false
ShowReadingTime: true
ShowShareButtons: true
ShowPostNavLinks: true
ShowBreadCrumbs: true
ShowCodeCopyButtons: true
ShowWordCount: true
ShowRssButtonInSectionTermList: true
UseHugoToc: true
disableSpecial1stPost: false
disableScrollToTop: false
comments: false
hidemeta: false
hideSummary: false
showtoc: true
tocopen: false
assets:
disableHLJS: true
disableFingerprinting: false
label:
text: "My Hugo Blog"
icon: /favicon.ico
iconHeight: 35
homeInfoParams:
Title: "Hi there 👋"
Content: Welcome to my blog.
socialIcons:
- name: twitter
url: "https://twitter.com/"
- name: github
url: "https://github.com/"
- name: linkedin
url: "https://linkedin.com/"
- name: rss
url: "/index.xml"
cover:
hidden: false
hiddenInList: false
hiddenInSingle: false
editPost:
URL: "https://github.com/username/repo/tree/main/content"
Text: "Suggest Changes"
appendFilePath: true
fuseOpts:
isCaseSensitive: false
shouldSort: true
location: 0
distance: 1000
threshold: 0.4
minMatchCharLength: 0
keys: ["title", "permalink", "summary", "content"]
menu:
main:
- identifier: search
name: Search
url: /search/
weight: 10
- identifier: posts
name: Posts
url: /posts/
weight: 20
- identifier: archives
name: Archives
url: /archives/
weight: 30
- identifier: tags
name: Tags
url: /tags/
weight: 40
- identifier: about
name: About
url: /about/
weight: 50
outputs:
home:
- HTML
- RSS
- JSON # Required for search functionalitybuildDrafts: falseenableRobotsTXT: trueminifyOutput: truedefaultTheme: autoJSON{
"name": "my-hugo-site",
"compatibility_date": "2025-01-29",
"assets": {
"directory": "./public",
"html_handling": "auto-trailing-slash",
"not_found_handling": "404-page"
}
}directory: "./public"html_handling: "auto-trailing-slash"not_found_handling: "404-page"# Hugo
/public/
/resources/_gen/
.hugo_build.lock
# OS
.DS_Store
Thumbs.db
# Editor
.vscode/
.idea/
*.swp
*.swo
# Dependencies (if using npm for tools)
node_modules/
package-lock.json
# Logs
*.logstatic/admin/index.html<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Content Manager</title>
</head>
<body>
<script src="https://unpkg.com/@sveltia/cms/dist/sveltia-cms.js" type="module"></script>
</body>
</html>static/admin/config.ymlbackend:
name: git-gateway
branch: main
local_backend: true # Enable local testing
media_folder: "static/images/uploads"
public_folder: "/images/uploads"
collections:
- name: "blog"
label: "Blog Posts"
folder: "content/posts"
create: true
slug: "{{slug}}"
fields:
- {label: "Title", name: "title", widget: "string"}
- {label: "Description", name: "description", widget: "string", required: false}
- {label: "Date", name: "date", widget: "datetime"}
- {label: "Draft", name: "draft", widget: "boolean", default: false}
- {label: "Tags", name: "tags", widget: "list", required: false}
- {label: "Categories", name: "categories", widget: "list", required: false}
- {label: "Cover Image", name: "cover", widget: "object", required: false, fields: [
{label: "Image", name: "image", widget: "image", required: false},
{label: "Alt Text", name: "alt", widget: "string", required: false}
]}
- {label: "Body", name: "body", widget: "markdown"}
- name: "pages"
label: "Pages"
folder: "content"
create: true
slug: "{{slug}}"
filter: {field: "type", value: "page"}
fields:
- {label: "Title", name: "title", widget: "string"}
- {label: "Date", name: "date", widget: "datetime"}
- {label: "Type", name: "type", widget: "hidden", default: "page"}
- {label: "Draft", name: "draft", widget: "boolean", default: false}
- {label: "Body", name: "body", widget: "markdown"}hugo
# Admin interface now at: http://localhost:1313/adminreferences/sveltia-integration-guide.md/adminlocal_backend: truestatic/images/uploadsreferences/tinacms-integration-guide.mdtailwind-v4-shadcn| Aspect | Vite + React | Hugo |
|---|---|---|
| Build System | JavaScript (Node.js) | Go (Hugo binary) |
| Tailwind Integration | | Tailwind CLI + PostCSS |
| Config File | | |
| Content Scanning | | |
| Dev Server | Vite (port 5173) | Hugo (port 1313) |
| Dark Mode | React ThemeProvider | CSS classes or Alpine.js |
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss inithugo.yamlbuild:
writeStats: true # Generates hugo_stats.json for Tailwind
module:
mounts:
- source: assets
target: assets
- source: hugo_stats.json
target: assets/watching/hugo_stats.jsontailwind.config.jsmodule.exports = {
content: [
'./hugo_stats.json',
'./layouts/**/*.html',
'./content/**/*.{html,md}',
],
darkMode: 'class',
theme: {
extend: {
colors: {
primary: '#0066cc',
},
},
},
plugins: [],
}postcss.config.jsmodule.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}assets/css/main.css@import "tailwindcss";
@layer base {
body {
@apply bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100;
}
}layouts/_default/baseof.html<head>
{{ $style := resources.Get "css/main.css" | resources.PostCSS }}
{{ if hugo.IsProduction }}
{{ $style = $style | minify | fingerprint }}
{{ end }}
<link rel="stylesheet" href="{{ $style.RelPermalink }}">
</head>hugo serverreferences/tailwind-v4-integration.mdtemplates/hugo-tailwind-minimal/templates/hugo-tailwind-blog/| Issue | Cause | Solution |
|---|---|---|
| CSS not processing | PostCSS not configured | Verify |
| Classes not purging | | Enable |
| Dark mode broken | Wrong config | Use |
| Asset fingerprinting fails | Incorrect Hugo Pipes usage | Use |
| Hugo template syntax in CSS | Can't use | Apply classes in templates, not CSS |
| Version mismatch | CLI vs PostCSS plugin | Update all to same version |
# Scaffold
hugo new site my-blog --format yaml
cd my-blog
git init
git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
# Configure (see hugo.yaml example above)
# Create posts
hugo new content posts/first-post.md
# Develop
hugo server
# Build
hugo --minify# Scaffold
hugo new site docs --format yaml
cd docs
git init
git submodule add https://github.com/alex-shpak/hugo-book.git themes/hugo-book
# Configure for docs (nested navigation, search)
# See: bundled template `templates/hugo-docs/`
# Create docs
hugo new content docs/getting-started/installation.md
# Build
hugo --minify# Scaffold
hugo new site landing --format yaml
# Use custom layouts (no theme)
# See: bundled template `templates/hugo-landing/`
# Single-page structure
hugo new content _index.md
# Build
hugo --minify# hugo.yaml
defaultContentLanguage: "en"
languages:
en:
languageName: "English"
weight: 1
es:
languageName: "Español"
weight: 2
# Content structure:
# content/
# ├── posts/
# │ └── post-1.en.md
# │ └── post-1.es.mdinit-hugo.sh./scripts/init-hugo.sh blog my-blog
# Creates Hugo site with specified template (blog/docs/landing/minimal)
# Arguments: [template-type] [project-name]deploy-workers.sh./scripts/deploy-workers.sh
# Runs: hugo --minify && wrangler deploycheck-versions.sh./scripts/check-versions.sh
# Checks: Hugo version, Extended edition, wrangler, Node.jstemplates/hugo-blog/templates/hugo-docs/templates/hugo-landing/templates/minimal-starter/references/sveltia-integration-guide.mdreferences/workers-deployment-guide.mdreferences/common-errors.mdreferences/theme-customization-guide.mdreferences/hugo-vs-alternatives.mdassets/screenshots/assets/diagrams/<!-- layouts/shortcodes/youtube.html -->
<div class="youtube-embed">
<iframe
src="https://www.youtube.com/embed/{{ .Get 0 }}"
allowfullscreen>
</iframe>
</div>{{< youtube dQw4w9WgXcQ >}}{{ $image := resources.Get "images/photo.jpg" }}
{{ $resized := $image.Resize "800x" }}
<img src="{{ $resized.RelPermalink }}" alt="Photo"># hugo.yaml
taxonomies:
tag: tags
category: categories
series: series # Custom taxonomy# data/team.yaml
- name: Alice
role: Developer
- name: Bob
role: Designer{{ range .Site.Data.team }}
<div>{{ .name }} - {{ .role }}</div>
{{ end }}hugo version | grep extendedthemethemes/git submodule update --init --recursivebaseURLhugo -b https://your-site.comdraft: false--buildDrafts--buildFuturesubmodules: recursivehugo/adminpublic/config.ymlhugo version--format yamlbaseURL.gitignorepublic/resources/_gen/hugo serverhugo --minifyreferences/common-errors.md