🎃

Hugo ことはじめ

に公開

この記事は,Hugo について全体を簡単にまとめたものです。

インストールについては こちら を参照してください。様々な方がコンテナイメージを作成していますので,それを参考にしても良いと思います。また,devcontainer 向けとして Hugo がモジュールとして提供されています。
https://github.com/devcontainers/features/pkgs/container/features%2Fhugo

🦜プロジェクトの作成 [1]

はじめにサイト(プロジェクト)を作成します。
新しいプロジェクトを作成するには,以下のコマンドを使用します。

hugo new site <Project名>

このコマンドを実行すると,指定した <Project名> のディレクトリが作成され,その中に Hugo プロジェクトのひな形が展開されます。

📁ディレクトリ構造 [2]

新規プロジェクト作成後のディレクトリ構成は以下のとおりです。

Project名/
├── archetypes/
│   └── default.md
├── assets/
├── content/
├── data/
├── i18n/
├── layouts/
├── static/
├── themes/  
└── hugo.toml    

以下,各ディレクトリ(一部ファイル含む)の説明です。

ディレクトリ 説明
archetypes hugo newで新規ページを作成する時のテンプレートを格納
assets パイプラインを通じて変換するSASSやJavaScriptなどを格納
content 記事やページなどのコンテンツをMarkdownファイルとしてここに配置
data サイト内で使う追加データ(YAML, JSON, TOML)を格納
i18n 多言語対応の翻訳ファイル
layouts レイアウトのテンプレートを格納
static 画像やCSSなど,そのまま出力される静的ファイルを格納
themes 使用するテーマを配置
hugo.toml プロジェクトの設定ファイル。config/_default/hugo.toml などと分割することも可能で,テーマによっては配置場所が異なる場合がある

hugoまたはhugo serverコマンドを実行することでサイト本体をビルドすることができ,この際に以下のディレクトリが追加されます。

ディレクトリ 説明
public ビルドされた静的サイトの出力先。デプロイ時にはこのフォルダの内容をサーバにアップロードする
resource パイプライン処理後のリソースキャッシュ用ディレクトリ。ビルド後のCSSや圧縮された画像が入る

⚙️設定ファイル[3][4]

Hugo の設定ファイルは初期ではhugo.tomlが用意されていますが,TOML,YAML,JSON形式で記述ができます。複数ファイルがある場合はhugo.tomlhugo.yamlhugo.json の順で読み込まれます。

以下は設定項目例です。有効な識別子とするため,キー名はキャメルケースまたはスネークケースを使用する必要があります。

baseURL = 'https://localhost:1313/'  # baseとなるURL
languageCode = 'en-us'               # 言語コード
title = 'My New Hugo Site'           # サイトのタイトル

[params]                             # カスタムパラメータ
  customCSS = ["./custom.css"]
  favicon = "./img/favicon.ico"

theme = "book"
enableGitInfo = true

1つの設定ファイルではなく,環境ごとや言語ごとに設定ファイルを分割することもできます。

設定ファイルの分割例
my-project/
└─ config/
    ├─ _default/
    │   ├─ hugo.toml
    │   ├─ menus.toml
    │   └─ params.toml
    ├─ production/
    │   ├─ hugo.toml
    │   ├─ params.toml
    └─ development/
        ├─ hugo.toml
        └─ params.toml

_default配下は文字通りデフォルトで読み込まれます。
production,developmentなどの環境ごとフォルダを作成し,次のコマンドのように--environmentで指定することで,_default設定に上書きし,各環境ごとの設定をすることができます。

hugo server --environment development

また--configを使うことで,ビルド時に特定のファイルを優先して読み込んだり,複数ファイルをマージすることも可能です。

設定ファイルを指定してサイトをビルドする
hugo --config custom.toml
2つ以上の設定ファイルを左から右の優先度で結合する
hugo --config hugo.toml,production/params.toml

環境変数によって設定を上書きすることもできます。環境変数は設定ファイルより優先されるため,CI/CD環境やコンテナ運用で有用です。

  • HUGO_BASEURLbaseURL
  • HUGO_ENABLEGITINFOenableGitInfo
  • HUGO_ENVIRONMENT:ビルド時の環境(production/development)

また,以下のコマンドにより,完全な設定構成を表示させることができます。

hugo config

📚コンテンツページ

コンテンツ自体はcontentディレクトリ配下にMarkdown記法で作成していきます。

ページを追加する

手動で Markdown ファイルを作成してもいいですが,CLIを使うとテンプレート付きのページを効率よく追加できます。

hugo new content content/post/test-page.md

このコマンドを実行すると,architypes/配下にあるテンプレートに基づいてページが生成されます。途中のディレクトリも自動で作成されるため,事前のフォルダ準備は不要です。

テンプレート例(architypes/default.md)
+++
date = '{{ .Date }}'
draft = true
title = '{{ replace .File.ContentBaseName "-" " " | title }}'
+++
作成されたページ例(content/post/test-page.md)
+++
date = '2025-05-31T07:00:11Z'
draft = true
title = 'Test Page'
+++

レイアウトテンプレート

レイアウトのテンプレートは,文字通りlayoutsディレクトリ配下にHTMLテンプレートとして配置します。
Hugoはレイアウトのテンプレートがないとレンダリングできません。テンプレートが用意されていない場合,ビルドしても「Page Not Found」と表示されてしまいます。そのため,とりあえず表示させたい場合,以下のような簡単なテンプレートをlayouts/all.htmlに置くだけでも動作します。

layouts/single.html
<h1>{{ .Title }}</h1>
{{ .Content }}

このテンプレートを使ってページをビルドすると,次のようにタイトルと本文だけが表示されます。

Theme

上記のレイアウトテンプレートを一から書くのが面倒,あるいはサイトの見た目を一気に整えたいという場合は,テーマを使うのが最も手っ取り早いです。
Theme一覧ページ から好みのものを選ぶことができます。適用方法は各ThemeのREADMEにあるかと思います。

デザインだけでなく事前に用意されている機能などにも違いがあるので,機能や作りたいページのイメージに合わせて選択します。

テンプレート構成例

各Themeのlayoutsディレクトリの中にもあると思いますが,トップページやページの一覧を表示するページ,末端のページなどでそれぞれ layout ファイルを作成することができます,構成はテーマによって異なりますが,以下は「book」テーマの一部を参考にしています。

構成例
layouts/
├─ post/               # セクションまたはタイプが「post」の際に使用
│   ├─ single.html
│   └─ list.html
├─ _shortcodes/        # Markdownファイル内で呼び出せる部品(ショートコード)
│   ├─ button.html
│   ├─ hint.html
│   └─ tab.html
├─ _partials/          # ヘッダー・フッター・メニューバーなどの再利用する部品
│   ├─ footer.html
│   ├─ header.html
│   ├─ menu.html
│   ├─ search.html
│   └─ toc.html
├─ baseof.html
├─ single.html
├─ list.html
├─ home.html
├─ 404.html
├─ term.html
├─ taxonomy.html
└─ all.html

様々なテンプレートファイルがありますが,簡単にまとめると以下のようなものがあります。

ファイル 説明
baseof.html サイト共通,文字通りbaseとなる部分
home.html トップページのレイアウト
single.html/page.html 通常のコンテンツページをレンダリング。page.htmlが存在しないとsingle.htmlにフォールバックされる
section.html セクション(/posts/など)配下のページ一覧をレンダリング。
term.html 各タグのページをデザイン。
taxonomy.html タグやカテゴリの一覧ページ
list.html home/section/taxonomy/termテンプレートが存在しない場合にフォールバック
all.html 上記すべてが存在しなかった場合の最終的なフォールバック先
_partials/ 再利用できるモジュールとしてのテンプレート。{{ partial "foo.html" . }}または partialCached で呼び出せる
_markup/ Markdown内の画像・リンク・見出しなどの要素のレンダリングを上書き
_shortcode/ コンテンツ内で呼び出せる部品

テンプレートの適用順[5]

各ページにどのテンプレートが最終的に使われるかは,「Content Type」「Page Kind」「Content type」「Section」「言語」「出力形式」に応じてHugoが採択します。この項目については一部後述します。

テンプレートの探索優先度については以下リンクなどにルールが詳細にかかれています。
https://github.com/gohugoio/hugo/pull/13541

・Page Kind[6]

各ページに紐づくそのページの種別です。以下5つの内から1つ,Hugo が自動で判別します。

Kind 説明
home トップページ
section 特定のセクション(ブログ一覧など)
page 個別のコンテンツページ
taxonomy タグやカテゴリの一覧ページ
term タグやカテゴリの個別ページ

以下のMethodで見ることができます。

{{ .Kind }}

・Section

content/配下の最上位ディレクトリ名です。
例えばcontent/posts/内のコンテンツはpostsがセクションになります。

・Content Type

Front Matterのtypeにて指定した値です。デフォルトではSectionと同じ値が入り,Sectionがない場合はpageになります。

🔖Front Matter [7]

マークダウンファイルの上部に記載する,メタデータの記述部分をFront Matterといいます。通常TAMLやTOML,JSON形式で記述します。

ここに記述することができるフィールドは以下のサイトにまとめられています。
https://gohugo.io/content-management/front-matter/

以下,一部抜粋です。

キー 説明
date ページに関連付ける日付
description HTMLファイルに変換した際に<meta name="description" content="">に紐付け
draft trueにすると,下書きファイルとしてビルド対象外にする
layout 適用するレイアウトを指定
summary 概要テキスト
title ページのタイトル
type コンテンツタイプ(Sectionを上書きする際に指定する)
weight ソート順を制御する整数。小さいほど先に表示
lastmod 最終更新日

また,自分でカスタムキーを追加することもできます。
この場合,以下のように[params]の下に追加します。(一応なくても問題ないですが,カスタムしたものと判別をつけるために入れたほうがいいかと思います)

+++
date = '2025-05-31T07:00:11Z'
draft = true
title = 'Test Page'
[params]
  customvalue = 'ABCD'
+++

カスタムキーは以下のMethodで呼び出すことができます。

Params[8]
まず.Paramsを見て,なければグローバル設定の.Site.Paramsも探します。どちらにもない場合,nullを返します

{{ .Params.customvalue }}

Param[9]
paramメソッドを使うと,動的にキー名を渡すことができます。

{{ .Param "customvalue" }}

🏗️サイトのビルド

hugoまたはhugo serverコマンドを実行することで静的ファイルをビルドすることができます。
コマンドの違いは以下の通りです。

  • hugo/hugo build[10][11]
    • 静的ファイルを生成
  • hugo server[12]
    • サーバーを立ち上げます。デフォルトでホットリロードを行います。

他にもサブコマンド及びオプション含めてさまざまありますので,詳細はドキュメントを確認ください。
https://gohugo.io/commands/

また,ビルドした静的サイトを Github Pages などのサービスと連携してサイトをホストしたい場合もあるかと思います。ここらの手順やサンプル設定については Hugo のサイトにて手順が案内されていますので,そちらを参考にしてみてください。
https://gohugo.io/host-and-deploy/

🧰Method[13]

ここまでで何度か出ているものですが,{{ ... }}を使った記述をすることで,動的に値を参照・加工する Method を使用することができます。
用意されている Method の詳細についてはこちらを参考にしてください。

以下はメソッドの一例です。

メソッド 説明
{{ .Title }} ページのタイトルを取得
{{ .Date }} Front Matterのdateを取得
{{ .Permalink }} ページのURLを取得
{{ .Summary }} ページの要約部分を返す。Front Matterのsummaryを取得
{{ .Site.Params.xxx }} 設定ファイルのparams以下に定義した値を取得
{{ .Site.Title }} サイト全体のタイトルを取得
{{ .Site.BaseURL }} baseURLを取得

似たもので Function もあります。

🔗URLまわり

おまけ程度の節ですが,URLについてです。
各ページのURLを設定する方法としては,以下の選択肢があります

  • Front Matter に記述するもの

    • url
    • aliases
    • slug
  • 設定ファイルに記述するもの

    • permalinks

url

Front Matterに記述することで,そのページの公開URLをルートから一括で指定します。

content/post/test-page.md
+++
url = "test/page"
+++

この場合,各パスのアクセス可否は次のようになります。

  • http://<domain>/post/test-page(フォルダパス):❌NG
  • http://<domain>/test/page(urlで指定したパス):⭕OK

このように,urlではフォルダ構成に関係なく任意のパスを設定できます。

aliases

aliasesにページの旧URLを設定することで,新URLへ自動リダイレクトを行うことができます。
相対パスの場合,そのmdファイルが存在する位置を起点としますので,意図しない動作になることがあります。そのため,できるだけ絶対パスで書くようにします。

content/post/test-page.md
+++
alius = "/test/page"
+++

上記の例の場合,各パスの表示は以下になります。

  • http://<domain>/post/test-page(フォルダパス):⭕OK
  • http://<domain>/test/page(aliasesで指定したパス):⭕/post/test-pageにリダイレクト
生成されるリダイレクトページ
<!DOCTYPE html>
<html lang="en-us">
  <head>
    <title>http://localhost:1313/post/test-page/</title>
    <link rel="canonical" href="http://localhost:1313/post/test-page/">
    <meta name="robots" content="noindex">
    <meta charset="utf-8">
    <meta http-equiv="refresh" content="0; url=http://localhost:1313/post/test-page/">
  </head>
</html>

古いURLを転送する場合に利用することが多いでしょうか

slug

slugはURLの最後の部分(slug)のみを変更します。

content/post/test-page.md
+++
slug = "test/page"
+++

上記の例の場合,各パスの表示は以下になります。

  • http://<domain>/post/test-page(フォルダパス):❌NG
  • http://<domain>/test/page(slugで指定したパス):❌NG
  • http://<domain>/post/test/page(フォルダパス+slug):⭕OK

構造に沿った形で名前だけ調整したいときに使えます。

より柔軟なURL構成が求められる場合,設定ファイルでpermalinksを使うことで,URLパターンを記述することもできます。

例えば以下の構成,設定を想定します。

例:コンテンツ構成
content/
├── posts/
│   ├── bash-in-slow-motion.md
│   └── tls-in-a-nutshell.md
├── tutorials/
│   ├── git-for-beginners.md
│   └── javascript-bundling-with-hugo.md
└── _index.md
例:config.toml
[permalinks]
  [permalinks.page]
    posts = '/articles/:year/:month/:slug/'
    tutorials = '/training/:slug/'
  [permalinks.section]
    posts = '/articles/'
    tutorials = '/training/'

この場合,ビルド後の構造は以下のようになります

public/
├── articles/
│   ├── 2023/
│   │   ├── 04/
│   │   │   └── bash-in-slow-motion/
│   │   │       └── index.html
│   │   └── 06/
│   │       └── tls-in-a-nutshell/
│   │           └── index.html
│   └── index.html
├── training/
│   ├── git-for-beginners/
│   │   └── index.html
│   ├── javascript-bundling-with-hugo/
│   │   └── index.html
│   └── index.html
└── index.html

ファイル単位ではなくセクション単位でURLルールを定義したい際に使うことができます。

上記の設定例はHugoのドキュメントからそのまま引用したものです。詳細は 公式ページ を参照してください。

🌐他参考サイト

https://piyopanman.dev/memos/hugo/
https://maku77.github.io/hugo/
https://gohugo.io/quick-reference/glossary/

脚注
  1. https://gohugo.io/commands/hugo_new_site/ ↩︎

  2. https://gohugo.io/getting-started/directory-structure/ ↩︎

  3. https://gohugo.io/configuration/all/ ↩︎

  4. https://gohugo.io/configuration/introduction/ ↩︎

  5. https://gohugo.io/templates/lookup-order/ ↩︎

  6. https://gohugo.io/methods/page/kind/ ↩︎

  7. https://gohugo.io/content-management/front-matter/ ↩︎

  8. https://gohugo.io/methods/page/params/ ↩︎

  9. https://gohugo.io/methods/page/param/ ↩︎

  10. https://gohugo.io/commands/hugo/ ↩︎

  11. https://gohugo.io/commands/hugo_build/ ↩︎

  12. https://gohugo.io/commands/hugo_server/ ↩︎

  13. https://gohugo.io/methods/ ↩︎

  14. https://gohugo.io/configuration/permalinks/ ↩︎

Discussion