- 技術 💻
Hugoとは・使い方|テーマ自作と1万記事のビルド実測・エラー原文
結論
Hugo(ヒューゴ)は、Markdown で書いた記事とテンプレートから、HTML だけのWebサイトを一度に書き出す静的サイトジェネレーターです。Go 言語で作られた1つの実行ファイルで動き、hugo new site→記事を書く→hugo server で確かめる→hugo で書き出す、の4段で使えます。
この記事でわかること
- インストールから公開用ファイルまでの手順と、各コマンドの実際の出力
- テーマの入れ方と、Hugo の版が合わないときに出るエラーの原文
- 記事1,000本・1万本のビルド時間と、テンプレート1行で半分になった実測
Hugo は「記事(Markdown)」「見た目(テンプレート・テーマ)」「設定(hugo.toml)」の3つを読み、public フォルダーに HTML・CSS・画像・RSS・サイトマップを書き出します。あとはそのフォルダーを置くだけで公開でき、サーバーでプログラムを動かす必要がありません。
flowchart TD
A[記事・テンプレート・設定] --> H[hugo コマンド]
H --> P[public フォルダー<br>HTML・CSS・RSS]
P --> S[静的ホスティングに置く]
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| Hugo とは | Go 製の静的サイトジェネレーター。Markdown から HTML を書き出す | Hugoとは |
| Hugo のインストール | Mac は brew、Windows は winget、Linux は公式の .deb か tar.gz | インストールと版の確かめ方 |
| Hugo の使い方(最初の4コマンド) | new site → new content → server → hugo | 使い方①・② |
| Hugo のテーマの入れ方 | themes/ に置いて hugo.toml に theme = '名前' |
テーマの入れ方 |
| テーマを入れたらエラーが出た | 多くは Hugo の版が足りないことが原因。テーマの最低版を見る | テーマの入れ方 |
| 記事が表示されない | draft = true か、日付が未来。-D・-F で確かめる |
使い方② |
| ビルドの速さ | 手元の2コアで記事1,000本が約0.8秒、1万本が約16秒 | ビルド時間を実測 |
| Astro・Next.js との違い | Hugo は Node.js も JavaScript も要らず、書き出し専用 | 違い(判断表) |
| どこで公開するか | GitHub Pages・Netlify・Cloudflare など静的ホスティング | ビルドして公開する |
確認環境:Ubuntu 24.04.5 LTS(Intel Xeon 2.10GHz・2 vCPU・メモリ 7.9GB、ほかの処理と同居)の上で、Ubuntu の公式リポジトリの hugo 0.123.7-1ubuntu0.3(extended)を apt-get download で取得し、依存する libsass1 3.6.5 とともに作業用のフォルダーへ展開して実行しました(システムには入れていません)。hugo new site・hugo new content・hugo server(127.0.0.1 の自分のポート)・hugo・hugo list・--templateMetrics の出力、自作の最小テーマ、テーマ Ananke の4つの版(git で取得)との組み合わせ、記事1,000本・5,000本・1万本の自動生成とビルド時間、エラー14種類を手元で確かめています。応答は curl 8.5.0 で見ました。最新版 v0.169.0(2026年10月27日公開)は GitHub のリリースページで確かめ、手元では動かしていません。v0.146.0 以降のテンプレートの新しい置き場所、Mac・Windows のインストール、ホスティング先、エディションの違いは公式ドキュメント(gohugo.io)で確かめました。図は mermaid で描画を確かめています(確認日 2026年10月29日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Hugoとは・使い方|テーマ自作と1万記事のビルド実測・エラー原文」
Hugoとは(静的サイトジェネレーターの仕組み)
この節では、Hugo が何をする道具で、WordPress のような仕組みと何が違うのかが分かります。
Hugo は、サイトを「見に来た時」ではなく「公開する前」に全ページを HTML にしておく道具です。このような道具を静的サイトジェネレーター(SSG:Static Site Generator)と呼びます。Hugo は Go 言語で書かれたオープンソース(Apache License 2.0)のソフトで、配布物は実行ファイル1つです。Node.js や Ruby などの実行環境を別に入れずに動きます。
静的サイト(Hugo)
公開前に全ページを HTML にして置いておく
サーバーはファイルを返すだけ。DB もプログラムも動かない
速く、攻撃される入口が少なく、置き場所の費用が安い
動的サイト(WordPress など)
アクセスのたびに PHP が DB を読んで HTML を作る
管理画面から誰でも記事を書ける
ログイン・コメント・検索などをサーバー側で処理できる
Hugo が向くのは、ブログ・企業サイト・製品ドキュメント・ポートフォリオのように、読む人ごとに中身が変わらないページです。問い合わせフォームやコメントのようにサーバー側の処理が要る部分は、外部のサービスや別の API と組み合わせます。
1速い
ビルドが速いことで知られる。手元の2コアでも、記事1,000本のサイトを1秒前後で書き出した。
2単体で動く
実行ファイル1つで、開発用サーバー・画像の縮小・Sass(extended 版)・RSS・サイトマップまで入っている。
3Markdown で書く
記事はテキストファイルなので Git で履歴を残せる。プルリクエストで記事をレビューする運用に向く。
苦手なところもあります。テンプレートは Go の text/template({{ }} で囲む書き方)で、HTML と JavaScript だけで書ける道具に比べると最初に覚えることが多めです。また、記事を書く人も Markdown とフォルダーの決まりを知っている必要があり、管理画面はありません。
Hugoのインストールと版の確かめ方(Mac・Windows・Linux)
この節では、OS ごとのインストールの方法と、standard 版・extended 版の選び方、版の確かめ方が分かります。
OS の標準のパッケージ管理で入れるのが簡単ですが、最新の版とは限らないため、入れたら必ず hugo version で版を見ます。公式ドキュメントに載っている方法は次のとおりです(Mac・Windows は手元で動かせないため、公式の記載だけを載せています)。
| OS | コマンド(公式) | 入る版 |
|---|---|---|
| Mac(Homebrew) | brew install hugo |
extended/deploy |
| Mac(MacPorts) | sudo port install hugo |
extended |
| Windows(WinGet) | winget install -e --id Hugo.Hugo.Extended |
extended |
| Windows(Chocolatey・Scoop) | choco install hugo-extended・scoop install hugo-extended |
extended |
| Linux(Snap) | sudo snap install hugo |
extended |
| Debian・Ubuntu | sudo apt install hugo |
extended(版はディストリビューション次第) |
| 全OS共通 | GitHub のリリースページからアーカイブ・.deb を取得 | 4種類から選ぶ |
公式ドキュメントは、リポジトリのパッケージについて「提供される版は最新とは限らない」と書いています。手元の Ubuntu 24.04 では、リポジトリの版は次のとおりで、2026年10月29日時点の最新 v0.169.0 からマイナー版で46前の版でした。
$ apt-cache policy hugo
hugo:
Installed: (none)
Candidate: 0.123.7-1ubuntu0.3
$ hugo version
hugo v0.123.7+extended linux/amd64 BuildDate=2025-07-18T03:41:49Z VendorInfo=ubuntu:0.123.7-1ubuntu0.3
Snap 版はサイトのフォルダーをホームかリムーバブルメディアに置く必要がある、と公式に注意書きがあります。Windows のパッケージ管理はどれも自動では更新されない、とも書かれています。
standard・extended・deploy の違い
| エディション | できること | 選ぶ場面 |
|---|---|---|
| standard | 基本の機能すべて | 迷ったらこれ(公式の案内) |
| deploy | 加えて Google Cloud Storage・AWS S3・Azure Storage へ直接デプロイ | hugo deploy を使う |
| extended | 加えて LibSass で Sass(SCSS)を CSS にする | テーマが SCSS を使う |
| extended/deploy | 上の両方 | 両方使う |
公式は「追加の機能が要らなければ standard を使う」と案内しています。なお、内蔵の LibSass は v0.153.0 で非推奨になり、将来の版で削除される予定で、Sass には Dart Sass が推奨されています。テーマの README に「extended が必要」とあれば extended を選びます。手元の版の中身は hugo env で見られます。
$ hugo env
hugo v0.123.7+extended linux/amd64 BuildDate=2025-07-18T03:41:49Z VendorInfo=ubuntu:0.123.7-1ubuntu0.3
GOOS="linux"
GOARCH="amd64"
GOVERSION="go1.22.2"
github.com/sass/libsass="3.6.5"
github.com/webmproject/libwebp="v1.3.2"
Hugoの使い方① hugo new siteでサイトを作る(フォルダー構成)
この節では、サイトのひな形を作るコマンドと、できあがるフォルダーそれぞれの役割が分かります。
最初に hugo new site 名前 で、空のサイトのひな形を作ります。手元の 0.123.7 で実行すると、次の案内が出ました。
$ hugo new site mysite
Congratulations! Your new Hugo site was created in /dev/shm/t87/mysite.
Just a few more steps...
1. Change the current directory to /dev/shm/t87/mysite.
2. Create or install a theme:
- Create a new theme with the command "hugo new theme <THEMENAME>"
- Install a theme from https://themes.gohugo.io/
3. Edit hugo.toml, setting the "theme" property to the theme name.
4. Create new content with the command "hugo new content <SECTIONNAME>/<FILENAME>.<FORMAT>".
5. Start the embedded web server with the command "hugo server --buildDrafts".
最新のドキュメント(v0.169.0 時点)のクイックスタートは、同じ操作を hugo new project quickstart と書いています。手元の 0.123.7 には new project の書き方がないため、版に合わせて読み替えます。
| できたもの | 入れるもの | メモ |
|---|---|---|
| hugo.toml | サイト全体の設定(URL・題名・テーマ) | yaml・json でも書ける。以前の版は config.toml |
| content/ | 記事の Markdown | フォルダー名がそのまま URL とセクションになる |
| layouts/ | サイト独自のテンプレート | テーマより優先される |
| themes/ | テーマ(テンプレート一式) | git の submodule で入れることが多い |
| static/ | そのまま公開するファイル(favicon・画像) | public/ の直下にコピーされる |
| assets/ | 加工してから使うファイル(SCSS・JS・画像) | テンプレートから縮小・結合する |
| archetypes/ | 新しい記事のひな形 | hugo new content で使われる |
| data/・i18n/ | テンプレートから読むデータ・翻訳 | 使わなければ空のまま |
作った直後の hugo.toml は3行だけです。日本語のサイトなら、少なくとも languageCode と title、公開先が決まったら baseURL を書き換えます。
baseURL = 'https://example.org/'
languageCode = 'en-us'
title = 'My New Hugo Site'
テーマを入れずにそのまま hugo を実行すると、エラーではなく警告が3行出て、HTML は1枚も作られませんでした。できたのは RSS とサイトマップだけです。
WARN found no layout file for "html" for kind "home": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN found no layout file for "html" for kind "taxonomy": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN found no layout file for "html" for kind "section": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
| EN
-------------------+-----
Pages | 5
...
Total in 7 ms
「画面が真っ白」「index.html ができない」のいちばん多い原因は、テーマ(テンプレート)が無いことです。Hugo は記事を HTML にする「型」を持っていないため、テーマを入れるか、自分でテンプレートを書きます。
Hugoの使い方② 記事を書く(フロントマター・下書き・予約投稿)
この節では、記事ファイルの作り方と、先頭に書く設定(フロントマター)、記事が表示されないときの確かめ方が分かります。
記事は hugo new content posts/ファイル名.md で作ります。archetypes/default.md がひな形になり、題名と日時が入ったファイルができます。
$ hugo new content posts/first-post.md
Content "/dev/shm/t87/mysite/content/posts/first-post.md" created
$ cat content/posts/first-post.md
+++
title = 'First Post'
date = 2026-10-30T05:37:43+09:00
draft = true
+++
先頭の +++ で囲んだ部分がフロントマター(記事ごとの設定)です。区切りの記号で書き方が決まります。
| 形式 | 区切り | 例 |
|---|---|---|
| TOML | +++ |
title = 'はじめての記事' |
| YAML | --- |
title: "はじめての記事" |
| JSON | { } |
"title": "はじめての記事" |
手元で使った記事の例です。TOML で書き、タグ・カテゴリー・説明文を付け、本文ではショートコード(後の節)を使っています。
+++
title = 'はじめての記事'
date = 2026-10-29T10:00:00+09:00
draft = false
tags = ['hugo', '入門']
categories = ['お知らせ']
description = 'Hugoで書いた最初の記事です。'
+++
Hugoで最初の記事を書きました。Markdownで書いた本文が、テーマのテンプレートに流し込まれてHTMLになります。
{{< note type="warn" >}}
**ショートコード**の中でも Markdown が使えます。
{{< /note >}}
次の記事は[2本目]({{< ref "second.md" >}})です。
よく使うフロントマターの項目
| 項目 | 意味 | メモ |
|---|---|---|
| title・date | 題名と日付 | 一覧の並び順にも使われる |
| draft | true なら下書き | -D(--buildDrafts)を付けたときだけ出る |
| publishDate・expiryDate | 公開日・公開終了日 | 未来の公開日は -F、期限切れは -E で出る |
| lastmod | 最終更新日 | サイトマップの lastmod に使われる |
| slug・url・aliases | URL の末尾・URL 全体・転送元 | aliases は以前の URL からの転送ページを作る |
| tags・categories | 分類(タクソノミー) | 一覧ページが自動でできる |
| description・summary | 説明文・要約 | description は meta 要素などに使う |
| weight・params・cascade | 並び順・独自の値・子ページへの継承 | 独自の項目は params の下に置く(公式) |
記事が出ないときは hugo list で確かめる
書いたのに出てこない記事は、ほとんどが「下書き」か「日付が未来」です。手元で、下書きの記事(draft = true)と、日付を 2026年12月1日にした記事を置いて確かめました。hugo list で一覧にすると、どちらの理由かがすぐ分かります。
$ hugo list drafts
path,slug,title,date,expiryDate,publishDate,draft,permalink
content/posts/draft.md,,下書きの記事,2026-10-29T13:00:00+09:00,0001-01-01T00:00:00Z,2026-10-29T13:00:00+09:00,true,https://example.com/posts/draft/
$ hugo list future
path,slug,title,date,expiryDate,publishDate,draft,permalink
content/posts/future.md,,予約投稿の記事,2026-12-01T09:00:00+09:00,0001-01-01T00:00:00Z,2026-12-01T09:00:00+09:00,false,https://example.com/posts/future/
| ビルドの仕方 | Pages | posts/ にできた記事 |
|---|---|---|
hugo |
21 | hello・second |
hugo server -D |
22 | hello・second・draft |
hugo -D -F |
23 | hello・second・draft・future |
予約投稿の記事は、日付を過ぎたあとにもう一度ビルドしたときに出ます。Hugo は時間がたっても自分では動かないため、予約投稿をするなら、CI で毎日ビルドするなどの仕組みを別に用意します。
記事のひな形は archetypes/ に「セクション名.md」を置くと、そのセクション用になります。手元で archetypes/posts.md にタグ・カテゴリー・説明文の欄を足すと、hugo new content posts/my-third-post.md で作った記事に、それらの空欄が最初から入りました。
hugo serverで確認する(127.0.0.1・ライブリロード)
この節では、書いた記事をブラウザで確かめる開発用サーバーの使い方と、保存してから画面に反映されるまでの流れが分かります。
hugo server は、ビルドしてからファイルの変更を見張り、保存するたびに作り直してブラウザを自動で再読み込みします。公式ドキュメントでは、待ち受けの既定は 127.0.0.1、ポートは 1313 です。手元ではほかの作業とぶつからないよう、ポートを指定して起動しました。
$ hugo server -D --bind 127.0.0.1 --port 48787 --baseURL http://127.0.0.1:48787/
Watching for changes in /dev/shm/t87/blog/{archetypes,assets,content,data,i18n,layouts,static,themes}
Watching for config changes in /dev/shm/t87/blog/hugo.toml
Start building sites …
hugo v0.123.7+extended linux/amd64 BuildDate=2025-07-18T03:41:49Z VendorInfo=ubuntu:0.123.7-1ubuntu0.3
| EN
-------------------+-----
Pages | 22
...
Built in 22 ms
Environment: "development"
Serving pages from disk
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://127.0.0.1:48787/ (bind address 127.0.0.1)
Press Ctrl+C to stop
curl で開くと、<head> の先頭にライブリロード用のスクリプトが差し込まれていました。hugo で書き出したファイルには入りません。
$ curl -i http://127.0.0.1:48787/posts/hello/
HTTP/1.1 200 OK
Content-Length: 2137
Content-Type: text/html; charset=utf-8
<!DOCTYPE html>
<html lang="ja">
<head><script src="/livereload.js?mindelay=10&v=2&port=48787&path=livereload" data-no-instant defer></script>
記事の1文を書き換えて保存すると、サーバーのログに次の行が出て、3ミリ秒で作り直されました。直後に curl で開くと、書き換えた文になっていました。
Change detected, rebuilding site (#1).
2026-10-30 05:39:09.213 +0900
Source changed /posts/hello.md
Total in 3 ms
下書きも見る
hugo server -D。draft = true の記事も出す。
本番のビルドには付けない
ポートを変える
--port 8080。使用中のポートを指定すると起動に失敗する。
既定は 1313
スマホから見る
--bind 0.0.0.0 --baseURL http://PCのIP:1313/。同じ LAN の端末から開ける。
社外の回線では使わない
全部作り直す
--disableFastRender。一部だけ反映されない時に付ける。
止めるのは Ctrl+C
公式は hugo server を「機能の限られた Web サーバー」と説明しています。確認のための道具で、公開には hugo で書き出したファイルを Web サーバーやホスティングに置きます。
Hugoのテーマの入れ方と、版が合わないときのエラー
この節では、テーマを入れる手順と、テーマが求める Hugo の版より手元の版が低いときに何が起きるかが、実際のエラーで分かります。
テーマは themes/ の下にフォルダーごと置き、hugo.toml に theme = 'フォルダー名' と書くと使われます。公式のクイックスタートは、Git の submodule で入れる方法を案内しています。
git init
git submodule add https://github.com/gohugo-ananke/ananke themes/ananke
echo "theme = 'ananke'" >> hugo.toml
hugo server
テーマは公式のテーマ一覧(themes.gohugo.io)から探せます。選ぶときは、見た目より先に「テーマが求める Hugo の最低の版」を見ます。テーマの theme.toml や config/_default/module.toml に書かれています。
手元の Hugo 0.123.7 で Ananke の版を変えて試した結果
公式のクイックスタートで使われるテーマ Ananke を、版を変えて4回入れ、Ubuntu の hugo 0.123.7 でビルドしました。
| Ananke の版 | 求める Hugo | 結果 |
|---|---|---|
| 最新(2026年9月27日のコミット) | 0.160.0 以上 | ERROR(can't evaluate field Locale) |
| v2.11.0(2024年10月) | 0.128.0 以上 | ERROR(can't evaluate field Sass) |
| v2.10.0(2024年9月) | theme.toml は 0.84.0、モジュール設定は 0.128.0 | ERROR(can't evaluate field Sass) |
| v2.9.2(2024年5月) | 指定なし | 成功(Pages 10・233 ms) |
最新の Ananke では、最初に警告が出たあと、テンプレートの実行でエラーになりました。
WARN Module "ananke" is not compatible with this Hugo version: Min 0.160.0; run "hugo mod graph" for more information.
...
ERROR render of "home" failed: "/dev/shm/t87/mysite/themes/ananke/layouts/baseof.html:2:15": execute of template failed: template: home.html:2:15: executing "home.html" at <site>: can't evaluate field Locale in type *langs.Language
Error: error building site: render: failed to render pages: render of "404" failed: ...
「is not compatible with this Hugo version」の警告が出たら、その後のエラーを読むより先に Hugo を新しくします。テンプレートが、手元の版にまだ無い機能(ここでは Locale や css.Sass)を使っているためです。テーマのファイルが layouts/baseof.html(_default の無い場所)にあるのも、v0.146.0 以降の新しい置き場所に合わせたものです。前の版の Hugo を使い続ける事情があるなら、v2.9.2 のように当時のテーマの版を選ぶと動きましたが、テーマの修正が入らなくなるため、Hugo を上げるほうを先に考えます。
テーマの一部だけを書き換える
テーマのファイルを直接書き換えると、テーマを更新したときに消えます。サイト側の layouts/ に同じ名前のファイルを置くと、そちらが優先されます。手元で、テーマの partials/head.html をサイトの layouts/partials/head.html にコピーし、1行足してビルドすると、トップと記事の両方にその行が入りました。サイト側のファイルを消すと元に戻りました。
テーマを直したいとき
見分ける問い:「テーマを入れ直しても、この変更は残るか」
最小のHugoテーマを自作する(テンプレートの基本)
この節では、外部のテーマを使わずに、ファイル7つで動く最小のテーマの中身と、テンプレートの書き方の基本が分かります。
テーマの中身は「どの種類のページを、どのテンプレートで HTML にするか」の集まりです。Hugo は、ページを home(トップ)・page(記事)・section(posts/ などの一覧)・taxonomy(タグの一覧)・term(1つのタグの記事一覧)の種類に分け、種類ごとにテンプレートを探します。手元で作った最小のテーマ mini は次の7ファイルです。
themes/mini/layouts/_default/baseof.html 全ページ共通の外枠
themes/mini/layouts/_default/home.html トップ(記事一覧とページ分け)
themes/mini/layouts/_default/single.html 記事1本
themes/mini/layouts/_default/list.html セクション・タグなどの一覧
themes/mini/layouts/partials/head.html head の中身
themes/mini/layouts/shortcodes/note.html 自作のショートコード
themes/mini/static/css/style.css CSS
外枠の baseof.html は、各ページの main の部分だけを差し替える形にします。
<!DOCTYPE html>
<html lang="{{ site.LanguageCode }}">
<head>
{{ partial "head.html" . }}
</head>
<body>
<header><a href="{{ "/" | relURL }}">{{ site.Title }}</a></header>
<main>{{ block "main" . }}{{ end }}</main>
<footer>© {{ now.Year }} {{ site.Title }}</footer>
</body>
</html>
記事1本の single.html です。{{ define "main" }} で囲んだ部分が、baseof.html の block "main" に入ります。
{{ define "main" }}
<article>
<h1>{{ .Title }}</h1>
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "2006年1月2日" }}</time>
{{ with .GetTerms "tags" }}<ul class="tags">{{ range . }}<li><a href="{{ .RelPermalink }}">#{{ .LinkTitle }}</a></li>{{ end }}</ul>{{ end }}
{{ .Content }}
</article>
{{ end }}
トップの home.html は、posts セクションの記事をページ分けして並べます(この書き方を選んだ理由は、ビルド時間の節で数字とともに説明します)。
{{ define "main" }}
<h1>{{ site.Title }}</h1>
{{ range (.Paginate (site.GetPage "/posts").RegularPages).Pages }}
<article>
<h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
<time>{{ .Date.Format "2006-01-02" }}</time>
<p>{{ .Summary }}</p>
</article>
{{ end }}
{{ template "_internal/pagination.html" . }}
{{ end }}
ビルドすると、記事1本は次の HTML になりました(抜粋)。タグの「hugo」は、一覧では先頭が大文字の「Hugo」になっています。日本語のタグは URL では %E5%85%A5%E9%96%80 のようにエンコードされます。
<title>はじめての記事 | ミニブログ</title>
<meta name="description" content="Hugoで書いた最初の記事です。">
<link rel="stylesheet" href="/css/style.css">
...
<h1>はじめての記事</h1>
<time datetime="2026-10-29">2026年10月29日</time>
<ul class="tags"><li><a href="/tags/hugo/">#Hugo</a></li><li><a href="/tags/%E5%85%A5%E9%96%80/">#入門</a></li></ul>
<p>Hugoで最初の記事を書きました。…</p>
<aside class="note note-warn"><strong>ショートコード</strong>の中でも Markdown が使えます。</aside>
テンプレートの書き方の基本
| 書き方 | 意味 | 例 |
|---|---|---|
{{ .Title }} |
今のページの値を出す | .Content・.Date・.Params.xxx |
{{ site.Title }} |
サイト全体の値 | site.Params.description |
{{ range … }}…{{ end }} |
繰り返し | 記事・タグを並べる |
{{ with … }}…{{ end }} |
値があるときだけ | タグが無い記事では何も出さない |
{{ "css/style.css" | relURL }} |
関数に値を渡す(パイプ) | サブフォルダーで公開しても崩れない |
{{ partial "head.html" . }} |
部品を読み込む | 最後の . で今のページを渡す |
日付の書式は Go の決まりで、2006-01-02 15:04 という「決まった日時」を見本として書きます。YYYY-MM-DD のようには書きません。
v0.146.0 からの新しい置き場所
公式ドキュメントによると、Hugo v0.146.0 でテンプレートの扱いが作り直され、置き場所が変わりました。以前の構成も対応表で読めるようにしてある、と書かれていますが、不具合の報告もあるとされています。新しく作るテーマは新しい置き場所に合わせます。
| 以前(0.123.7 で使用) | v0.146.0 以降 |
|---|---|
| layouts/_default/baseof.html など | layouts/baseof.html(_default は廃止) |
| layouts/partials/ | layouts/_partials/ |
| layouts/shortcodes/ | layouts/_shortcodes/ |
| layouts/index.html(トップ) | layouts/home.html |
| taxonomy.html を term にも使う | taxonomy.html と term.html を分ける |
コマンドで作るなら hugo new theme 名前 で、ヘッダー・メニュー・CSS・サンプル記事まで入ったひな形(手元の 0.123.7 では25ファイル)ができます。中身を読みながら削っていくと、テンプレートの仕組みを覚えやすくなります。
タクソノミー・ショートコード・画像処理の使い方
この節では、タグやカテゴリーの一覧ページ、記事の中で使う部品(ショートコード)、画像の縮小の3つが、実際の出力とともに分かります。
タクソノミー(タグ・カテゴリー)
フロントマターに tags と categories を書くだけで、Hugo は一覧ページと RSS を自動で作ります。設定で何も書かなくても tags と categories は使えます。手元の hugo.toml では明示しました。
[taxonomies]
tag = 'tags'
category = 'categories'
記事2本(タグ3種・カテゴリー2種)でビルドすると、次のファイルができました。
public/tags/index.html
public/tags/hugo/index.html
public/tags/hugo/index.xml
public/tags/テンプレート/index.html
public/tags/入門/index.html
public/categories/index.html
public/categories/お知らせ/index.html
public/categories/技術/index.html
ショートコード(記事の中で使う部品)
ショートコードは、Markdown に書けない部品を {{< 名前 >}} の形で呼び出す仕組みです。公式ドキュメントに載っている組み込みのショートコードは details・figure・highlight・instagram・param・qr・ref・relref・vimeo・x・youtube の11種類です。手元では組み込みの ref と highlight、自作の note を使いました。
<aside class="note note-{{ .Get "type" | default "info" }}">{{ .Inner | markdownify }}</aside>
これを layouts/shortcodes/note.html に置くと、記事の中で {{< note type="warn" >}}…{{< /note >}} と書けます。ref は記事のファイル名から URL を作るので、URL を変えてもリンクが切れません。手元では {{< ref "second.md" >}} が https://example.com/posts/second/ になりました。
| 書き方 | 処理の順番(公式) | 使う場面 |
|---|---|---|
{{< 名前 >}} |
別に処理して、Markdown の変換後に合わせる | HTML を出す部品 |
{{% 名前 %}} |
Markdown の変換の前に処理する | 中に見出しを書き、目次に載せたい |
Markdown の中に HTML を直接書くと、既定では出力されません。手元で <span style="color:red"> を書いた記事をビルドすると、その部分が「raw HTML omitted」という HTML コメントに置き換わりました。HTML をそのまま出すには設定の [markup.goldmark.renderer] unsafe = true が要りますが、記事を書く人が多いサイトでは、ショートコードで必要な部品だけを用意するほうが安全です。
画像の縮小(ページバンドル)
記事を「フォルダー+index.md」の形(ページバンドル)にすると、同じフォルダーの画像をテンプレートから加工できます。800×400 の PNG(100,757 バイト)を置き、次のショートコードで幅400の WebP にしました。
{{ with .Page.Resources.Get (.Get 0) }}
{{ $img := .Resize "400x webp q75" }}
<img src="{{ $img.RelPermalink }}" width="{{ $img.Width }}" height="{{ $img.Height }}" alt="">
{{ end }}
加工した画像は resources/_gen/ にも保存され、2回目からは変換し直さずに使われます。このフォルダーは Git に入れておくと CI のビルドが速くなり、入れなければ毎回変換します。
hugoでビルドして公開する(publicの中身とデプロイ先)
この節では、公開用のファイルを書き出すコマンドと、できるファイル、サブフォルダーで公開するときの注意、置き場所の選び方が分かります。
公開用のファイルは、オプションを付けずに hugo と打つと public/ に書き出されます。最新のドキュメントでは hugo build とも書かれていますが、手元の 0.123.7 では次のエラーになりました。以前の版では hugo だけで書き出します。
$ hugo build
Error: command error: unknown command "build" for "hugo"
記事3本(1本は画像つき)のサイトをビルドした結果です。
$ hugo
Start building sites …
hugo v0.123.7+extended linux/amd64 BuildDate=2025-07-18T03:41:49Z VendorInfo=ubuntu:0.123.7-1ubuntu0.3
| EN
-------------------+-----
Pages | 24
Paginator pages | 0
Non-page files | 0
Static files | 1
Processed images | 1
Aliases | 1
Cleaned | 0
Total in 24 ms
表の「EN」は、languageCode = 'ja' にしても変わりませんでした。これは表示用の言語の区分(defaultContentLanguage の既定値 en)で、hugo config で見ると defaultcontentlanguage = 'en' のままでした。HTML の lang="ja" は languageCode から出ています。
| オプション | 働き | 手元の結果 |
|---|---|---|
| なし | public/ に書き出す | 28ファイル。HTML 計10,940バイト |
--minify |
HTML・XML などの空白を詰める | HTML 計10,093バイト(約8%減) |
--gc |
使われなくなったキャッシュを消す | resources/_gen の掃除 |
--cleanDestinationDir |
出力先の不要なファイルを消す | 消した記事の HTML が残らない |
-d フォルダー |
出力先を変える | public/ 以外に書き出す |
--baseURL |
公開先の URL を上書きする | CI でプレビュー用の URL にする |
記事を消しても、public/ にある以前の HTML は自動では消えません。公開の前に public/ を消してからビルドするか、--cleanDestinationDir を付けます。
サブフォルダーで公開するとき(baseURL と relURL)
GitHub Pages のプロジェクトサイトのように https://example.com/blog/ の下で公開するときは、baseURL にフォルダーまで書きます。手元で baseURL を https://example.com/blog/ にすると、テンプレートで relURL を通した CSS とタグのリンクは /blog/css/style.css・/blog/tags/hugo/ になりました。テンプレートに /css/style.css と直接書いた場合は /css/style.css のまま出力され、公開先では CSS が読み込めない形になりました。
サイトマップと予約投稿の記事
sitemap.xml には公開した13の URL が入り、日付が未来の記事は入りませんでした。ただし、手元の 0.123.7 では、トップと posts/ の lastmod が未来の記事の日付(2026-12-01)になっていました。予約投稿を置いたまま公開する場合は、公開前に sitemap.xml の lastmod も見ておきます。
デプロイ先
public/ はただのファイルの集まりなので、静的ファイルを置ける場所ならどこでも公開できます。公式ドキュメントの「Host and deploy」には、AWS Amplify・Azure Static Web Apps・Cloudflare・Codeberg Pages・Firebase・GitHub Pages・GitLab Pages・Netlify・Render・Vercel と、FTP・Rclone・Rsync・Hugo CLI(hugo deploy)での手順が載っています。
- GitHub Pages:GitHub Actions で hugo を動かして公開する形が一般的です。公開の方法と独自ドメイン・404 の直し方は、関連記事「GitHub Pagesとは|使い方・公開3通り・独自ドメインと404の直し方」で扱っています。
- Netlify:ビルドのコマンドに
hugo、公開するフォルダーにpublicを指定します。画面の操作とエラーの対処は、関連記事「Netlifyとは|使い方・料金・デプロイ方法とエラー対処を実例で」で扱っています。 - どこでも共通:CI で使う Hugo の版を、手元と同じ版に固定します。版が違うと、手元では動くテーマが CI では前の節のエラーになります。
Hugoのビルド時間を実測(記事1,000本・5,000本・1万本)
この節では、記事の数を増やしたときに Hugo のビルド時間がどう伸びるかと、テンプレートの書き方1つで時間が半分になった例が分かります。
記事を Python で自動生成し、自作のテーマ mini で5回ずつビルドしました。記事は1本あたり約8KB(見出し・本文5段落・Go のコードブロック1つ・タグ3つ、タグは全部で50種類)です。手元は2 vCPU でほかの処理と同居しているため、数値には振れがあります。表は5回の中央値です。
| 記事数 | Pages | 書き換え前の home.html | 書き換え後の home.html | 出力 |
|---|---|---|---|---|
| 1,000本 | 1,109 | 0.90秒 | 0.77秒 | 1,310ファイル・11MB |
| 5,000本 | 5,109 | 9.8秒 | 5.7秒 | 6,110ファイル・54MB |
| 1万本 | 10,109 | 32.9秒 | 15.8秒 | 12,110ファイル・107MB |
書き換え前は、記事が5倍・10倍になると、時間が11倍・37倍に伸びていました。--templateMetrics で、どのテンプレートに時間がかかっているかを見ると、トップの home.html が飛び抜けていました(5,000本のとき)。
$ hugo --templateMetrics
cumulative average maximum
duration duration duration count template
---------- -------- -------- ----- --------
10.712942233s 10.712942ms 102.679666ms 1000 _default/home.html
8.147165199s 1.629433ms 62.316252ms 5000 _default/single.html
790.128661ms 14.632012ms 232.919646ms 54 _internal/_default/rss.xml
トップは5本ずつのページ分けで1,000ページあり、その1ページごとに where site.RegularPages "Section" "posts" が全記事を調べ直していました。記事数×ページ数で増えるため、記事が増えるほど急に遅くなります。
トップで posts の記事を並べるとき
.Paginate (where site.RegularPages "Section" "posts")。ページごとに全記事を絞り込み直す。home.html の合計 10.7秒.Paginate (site.GetPage "/posts").RegularPages。セクションが持つ一覧をそのまま使う。合計 2.6秒見分ける問い:「ページ分けの1ページごとに、全記事を調べていないか」
参考に、本文が1行だけの記事1,000本では0.52〜1.08秒でした。本文の長さとコードの色付けも時間に効きますが、それ以上に「1ページごとに全記事を回す処理」がテンプレートのどこかにあるかで、記事が増えたときの時間が大きく変わります。外部のテーマを使っていて遅いと感じたら、まず --templateMetrics で上位のテンプレートを見ます。--templateMetricsHints を足すと、partialCached に置き換えられそうな部品の候補も表示されます。
Hugoのよくあるエラーと直し方(原文つき)
この節では、Hugo を使い始めたときによく出るエラーの原文と、原因と直し方が一覧で分かります。
Hugo のエラーは「ファイルのパス:行:列」が付いているので、まずその場所を開きます。手元の 0.123.7 でわざと起こしたエラーです。
| エラーの原文(抜粋) | 原因 | 直し方 |
|---|---|---|
| Unable to locate config file or config directory. Perhaps you need to create a new site. | サイトのフォルダーの外で実行した | hugo.toml のあるフォルダーへ cd する |
| module "nothere" not found in ".../themes/nothere"; either add it as a Hugo Module or store it in ".../themes". | theme の名前と themes/ のフォルダー名が違う・submodule が空 | 名前を合わせる。git submodule update --init |
| Module "ananke" is not compatible with this Hugo version: Min 0.160.0 | テーマが求める版より Hugo の版が低い | Hugo を上げる |
| found no layout file for "html" for kind "home" | テーマが無い・テンプレートが足りない | テーマを入れる。該当の種類のテンプレートを作る |
| parse failed: template: _default/single.html:9: unexpected EOF | {{ end }} が足りない |
range・with・if・define の数と end の数を合わせる |
| can't evaluate field Contnet in type *hugolib.pageState | ページの値の名前の打ち間違い | .Content のように正しい名前にする |
| failed to unmarshal YAML: yaml: line 2: did not find expected key | YAML のフロントマターの書き方の誤り(引用符の閉じ忘れ) | 値を "…" で正しく囲む |
| unmarshal failed: toml: incomplete number | TOML で文字列を引用符で囲んでいない | title = '…' と囲む |
| failed to extract shortcode: template for shortcode "youtube2" not found | 無いショートコードを呼んだ | 名前を確かめる。layouts/shortcodes/ に作る |
| shortcode "note" must be closed or self-closed | 閉じタグ {{< /note >}} が無い |
閉じタグを書く |
| REF_NOT_FOUND: Ref "nothere.md": … page not found | ref で指定した記事が無い・下書き | ファイル名を確かめる |
| unknown command "build" for "hugo" | Hugo の版が低い(build は新しい版の書き方) | hugo だけで書き出す |
| server startup failed: listen tcp 127.0.0.1:48787: bind: address already in use | 指定したポートを別のプロセスが使っている | 別の --port を指定するか、前のサーバーを止める |
エラーにならないつまずきもあります。
- 記事が出ない:draft = true、日付が未来、expiryDate を過ぎた、のどれか。
hugo list drafts・hugo list futureで確かめます。 - Markdown に書いた HTML が消える:既定では「raw HTML omitted」に置き換わります。前の節のとおりです。
- CSS が当たらない(公開先だけ):baseURL とテンプレートのパスの書き方。relURL・absURL を通します。
- 保存しても画面が変わらない:
--disableFastRenderを付けて起動し直します。
- 1hugo version と CI の版が同じかテーマの最低の版も満たしているか
- 2baseURL が公開先の URL かサブフォルダーで公開するならフォルダーまで書く
- 3-D を付けずにビルドしたか下書きを公開しない
- 4public/ を消してからビルドしたか消した記事の HTML を残さない
- 5WARN の行が出ていないかテンプレートが無い種類のページは HTML ができない
Astro・Next.js・WordPressとの違い(どれを選ぶか判断表)
この節では、Hugo と、よく比べられるサイト作りの道具の違いと、どんなときに Hugo を選ぶかが分かります。
Hugo は「Markdown の記事が多いサイトを、JavaScript の環境なしで速く書き出す」ことに向いています。画面の動きが多いサイトや、React の部品を使いたい場合は、Astro や Next.js が候補になります。
| Hugo | Astro | Next.js | WordPress | |
|---|---|---|---|---|
| 書く言語 | Markdown+Go テンプレート | Markdown・.astro・React など | React(JSX・TSX) | 管理画面+PHP テーマ |
| 動かすのに要るもの | hugo の実行ファイルだけ | Node.js と npm | Node.js と npm | PHP と MySQL のサーバー |
| 出力 | 静的ファイルだけ | 静的が基本、サーバー処理も可 | 静的・サーバー処理の両方 | アクセスのたびに生成 |
| 記事を書く人 | Git とファイルを扱える人 | 同左 | 同左(CMS と組み合わせることが多い) | 管理画面を使える人 |
| 向くサイト | 記事・ドキュメントが多いサイト | 記事中心で一部に動きのあるサイト | ログインなど機能の多い Web アプリ | 書く人が多い・更新が多いサイト |
- 1管理画面から書く人が多い → WordPress やヘッドレス CMSGit を使わない人が記事を書く
- 2ログイン・決済などサーバー側の処理が中心 → Next.js静的サイトの範囲を超える
- 3記事中心だが React の部品を一部で使いたい → Astro必要な部品だけ JavaScript を送れる
- 4Markdown の記事・ドキュメントが中心で、Node.js を入れたくない → Hugo数千本でもビルドが短い
Next.js の App Router の作り方とビルドの出力は、関連記事「Next.js App Router 入門|v16対応・実際のビルド結果つき」で扱っています。Hugo の記事で使う Markdown の記法は関連記事「Markdownの書き方一覧|記法早見表と環境別の対応・変換結果つき」で、hugo.toml の TOML と YAML の違いは関連記事「CSV・JSON・XML・YAML・TOMLの違いと使い分け|同じデータで比較」で扱っています。
よくある質問
Q. Hugo とは何ですか? A. Go 言語で作られた静的サイトジェネレーターです。Markdown の記事とテンプレートから、HTML・CSS・RSS・サイトマップを public/ フォルダーに書き出します。書き出したファイルを置くだけで公開できます。
Q. Hugo は無料ですか? A. オープンソース(Apache License 2.0)で、無料で使えます。費用がかかるとすれば、公開に使うホスティングとドメインです。
Q. Go 言語を知らなくても使えますか?
A. 使えます。Go 言語のプログラムを書くことはありません。テンプレートは Go の text/template の書き方({{ .Title }} など)を使いますが、テーマを使うだけならテンプレートを書かずに始められます。
Q. standard 版と extended 版のどちらを入れればよいですか? A. 公式は「追加の機能が要らなければ standard」と案内しています。テーマが SCSS を使っていて README に extended が必要と書かれていれば extended を選びます。Mac の brew、Windows の winget で入るのは extended です。
Q. テーマを入れたらエラーになりました。 A. 最初に「is not compatible with this Hugo version: Min …」の警告が出ていないかを見ます。出ていれば Hugo の版が足りないことが原因です。手元では、Ubuntu の apt で入る 0.123.7 に最新の Ananke を入れると「can't evaluate field Locale」で止まりました。
Q. 書いた記事が表示されません。
A. フロントマターの draft が true か、date・publishDate が未来の日時になっていることが多いです。hugo list drafts と hugo list future で確かめ、確認だけなら hugo server -D -F で表示できます。
Q. hugo server で作ったページをそのまま公開できますか?
A. 公開には使いません。hugo server は確認用で、ライブリロードのスクリプトが差し込まれます。hugo で書き出した public/ を Web サーバーやホスティングに置きます。
Q. 記事が何本くらいまで実用的にビルドできますか?
A. 手元の2 vCPU では、1万本で約16秒でした。ただし、テンプレートの書き方次第で倍以上かかることがあり、同じ1万本で書き換え前は約33秒でした。遅いときは --templateMetrics で原因のテンプレートを探します。
Q. WordPress から Hugo へ移せますか? A. 記事を Markdown に書き出せば移せます。ただしコメント・問い合わせフォーム・会員機能など、サーバー側で動いていた機能は、外部のサービスで置き換える必要があります。URL を変えるなら、フロントマターの aliases で以前の URL からの転送ページを作れます。
Q. config.toml と hugo.toml の違いは?
A. どちらも設定ファイルです。新しい版の hugo new site は hugo.toml を作ります。手元の 0.123.7 の help には「config file (default is hugo.yaml|json|toml)」と表示されました。
まとめ
- Hugo は Go 製の静的サイトジェネレーター。
hugo new site→hugo new content→hugo server→hugoの4段で使え、public/ を置くだけで公開できる。 - OS のパッケージは最新の版とは限らない。手元の Ubuntu 24.04 の apt は 0.123.7 で、2026年10月29日時点の最新 v0.169.0 とはマイナー版で46の差があった。
- テーマのエラーは、まず版を疑う。最新の Ananke は Hugo 0.160.0 以上を求め、0.123.7 では「can't evaluate field Locale」で止まった。v0.146.0 以降はテンプレートの置き場所も変わっている。
- テーマは直接書き換えず、サイトの layouts/ に同じパスで置いて上書きする。最小のテーマはファイル7つで作れた。
- 記事1万本のビルドは約16秒。トップのページ分けで
where site.RegularPagesを使うと約33秒かかり、site.GetPage "/posts"に変えるだけで半分になった。
参考・出典
確認日はいずれも 2026年10月29日です。
- Hugo「Quick start」:https://gohugo.io/getting-started/quick-start/
- Hugo「Linux」(インストール):https://gohugo.io/installation/linux/
- Hugo「macOS」(インストール):https://gohugo.io/installation/macos/
- Hugo「Windows」(インストール):https://gohugo.io/installation/windows/
- Hugo「hugo server」:https://gohugo.io/commands/hugo_server/
- Hugo「hugo build」:https://gohugo.io/commands/hugo_build/
- Hugo「hugo new project」:https://gohugo.io/commands/hugo_new_project/
- Hugo「Front matter」:https://gohugo.io/content-management/front-matter/
- Hugo「Shortcodes」:https://gohugo.io/content-management/shortcodes/
- Hugo「New template system overview」:https://gohugo.io/templates/new-templatesystem-overview/
- Hugo「Configure pagination」:https://gohugo.io/configuration/pagination/
- Hugo「Host and deploy」:https://gohugo.io/host-and-deploy/
- Hugo Themes:https://themes.gohugo.io/
- GitHub「gohugoio/hugo Releases」(v0.169.0):https://github.com/gohugoio/hugo/releases
- GitHub「theNewDynamic/gohugo-theme-ananke」:https://github.com/theNewDynamic/gohugo-theme-ananke
- Ubuntu 24.04 のリポジトリ(noble-updates/universe・noble-security/universe)の hugo 0.123.7-1ubuntu0.3:
apt-cache policy hugoで確認
Hugo の実行ファイルは Go 言語で作られています。Go そのものの文法は関連記事「Go言語入門|1.27対応の基本文法を実行結果つきで解説」で扱っています。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Hugoとは・使い方|テーマ自作と1万記事のビルド実測・エラー原文」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。