作ったものとか » Hugo テーマ

Hugo テーマ 3. 作られたファイル

2026-05-28 21:26:15 Hugo
最終更新日から %s 以上が経過しています。
内容が古くなっている可能性があるのでご注意ください。

前回作ったテーマを構成するファイルを確認します。

hugo new theme でできたファイル

前回で作成されたファイルの一覧を、簡単な説明付きで再掲します。

\---themes
    \---derty
        |   hugo.toml               ← テーマの情報、テーマがデフォルトとして指定する設定
        |
        +---archetypes              ← (削除)
        |       default.md
        |
        +---assets                  ← Hugo Pipes で処理されるファイルを置く
        |   +---css
        |   |   |   main.css
        |   |   |
        |   |   \---components
        |   |           footer.css
        |   |           header.css
        |   |
        |   \---js
        |           main.js
        |
        +---content                 ← (削除) 動作確認中は残しておいてもよいかも
        |   |   _index.md
        |   |
        |   \---posts
        |       |   post-1.md
        |       |   post-2.md
        |       |   _index.md
        |       |
        |       \---post-3
        |               bryce-canyon.jpg
        |               index.md
        |
        +---data                    ← (削除)
        +---i18n                    ← (削除)
        +---layouts                 ← 今回の主役。(ほぼ毎回主役)
        |   |   baseof.html         ← ★ すべての種類のページのもととなる
        |   |   home.html           ← ★ サイトのトップページ
        |   |   page.html           ← ★ コンテンツ単体に対応する
        |   |   section.html        ← ★ content/section1/content1-1.md の section1 に対応する
        |   |   taxonomy.html       ← ★ タグなど、設定ファイルの [taxonomies] で定義した分類を列挙する
        |   |   term.html           ← ★ タグなど、コンテンツごとに定義した分類値を持つページを列挙する
        |   |
        |   \---_partials           ← ★ 共通部品など、繰り返し現れるページの構成要素をくくりだしたもの
        |       |   footer.html
        |       |   head.html
        |       |   header.html
        |       |   menu.html
        |       |   terms.html
        |       |
        |       \---head
        |               css.html
        |               js.html
        |
        \---static                  ← (削除) 固定ファイル
                favicon.ico

以下では、この内容のうち layouts の内容を取り上げます。

Tip

説明することがらは最低限にとどめています。が、それにしても長くなってしまいました。
ファイルの内容も記載していますが、どちらかというとその前の説明を見てから参照する程度で大丈夫です。

というか、以下の点を押さえておけばこの記事は飛ばしてしまっても問題ないような気も…?

Important

  • いろいろな種類のページがある
  • ページの種類に応じて Hugo が page.htmlsection.html といったレイアウト定義を選択して使う
  • 集合を扱うような種類のページでは {{ range .Pages }} ... {{ end }} で繰り返し処理をする
  • baseof.html がブラウザーで表示されるページの枠組みを担当しており、page.htmlsection.html といったレイアウト定義はその枠組みの中の main という一部分のレイアウト定義を担当している
  • _partials には共通して出現する構造を部品として置いておくことができ、{{ partial "xxx.html" . }} という形で様々な場所から利用することができる (xxx.html には、_partials 以下のパスを書く)

layouts/baseof.html

サイト内で生成される HTML ファイルに共通する構造を定義します。

下にファイルの内容を載せます。 この中の main の部分がページの種類に応じた内容で置き換わるのですが、この baseof.html ではそれ以外でページを構成する部分を定義します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="{{ site.Language.Locale }}" dir="{{ or site.Language.Direction `ltr` }}">
<head>
  {{ partial "head.html" . }}
</head>
<body>
  <header>
    {{ partial "header.html" . }}
  </header>
  <main>
    {{ block "main" . }}{{ end }}
  </main>
  <footer>
    {{ partial "footer.html" . }}
  </footer>
</body>
</html>

より突っ込んで知りたい方へ

layouts/home.html

サイトのトップページ (ホームページ) に対する main の内容を定義しています。

最終的に、上記の baseof.html の枠組みにこの home.html の内容があてはめられてトップページとして出力されます。

1
2
3
4
5
6
7
8
9
{{ define "main" }}
  {{ .Content }}
  {{ range site.RegularPages }}
    <section>
      <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
      {{ .Summary }}
    </section>
  {{ end }}
{{ end }}

ざっくり解説

コンテンツに対応するページ (site.RegularPages) それぞれについて、そのリンクとタイトルを出力しています。

より突っ込んで知りたい方へ

layouts/page.html

個々のコンテンツに対応するレイアウトを定義します。

home.html 同様、main の内容を定義しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{{ define "main" }}
  <h1>{{ .Title }}</h1>

  {{ $dateMachine := .Date | time.Format "2006-01-02T15:04:05-07:00" }}
  {{ $dateHuman := .Date | time.Format ":date_long" }}
  <time datetime="{{ $dateMachine }}">{{ $dateHuman }}</time>

  {{ .Content }}
  {{ partial "terms.html" (dict "taxonomy" "tags" "page" .) }}
{{ end }}

ざっくり解説

コンテンツ (xxx.md) のタイトル (.Title) や記述されたファイルの内容 (.Content) を出力しています。
対象としているコンテンツはピリオドから始まる式 (例: {{ .Title }}) で参照します。

より突っ込んで知りたい方へ

layouts/section.html

セクション内のコンテンツを一覧表示するようなレイアウトを定義します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}
  {{ range .Pages }}
    <section>
      <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
      {{ .Summary }}
    </section>
  {{ end }}
{{ end }}

ざっくり解説

セクション自身 (自身…セクションのディレクトリー直下にある _index.md) のタイトル (.Title) や記述されたファイルの内容 (.Content) を出力し、 さらにそのセクション内のコンテンツやサブセクションのタイトル等を出力しています。

ざっくり解説: セクションもコンテンツもページ

上のざっくり説明で触れましたが、コンテンツのみならず、セクションも、なんなら分類や分類値など、結構な概念が Hugo 上ではページ (Page) として扱われます。

そのため、上記のレイアウト定義における .Pages は、コンテンツ以外にもセクション (正確は、対象としているセクション内のコンテンツやサブセクション) がすべて入った「ページ」の集合を意味しています。。


なお、セクションそれ自身にもタイトルやコンテンツを持つことができます。

content/  
  section1/
    content1-1.md
  section2/
    _index.md       ← section2 のコンテンツ
    content2-1.md

たとえば content/section2/_index.md を以下のように記述します。

---
title: "section2 です"
---

hello

これで、上記のレイアウト定義にある .Title は “section2 です” になり、.Content は “hello” になります。

より突っ込んで知りたい方へ

layouts/taxonomy.html …の前に、分類 (taxonomy) について

Tip

taxonomy.htmlterm.html は、タグ等の taxonomy に関するものです。

思いのほか込みいった説明になってしまいました。
ここについては、必要に応じて後から読み返すことを推奨します。

分類 (taxonomy)

分類 (taxonomy) としてどのようなものを使うかは、プロジェクトの config.toml で定義します。

[taxonomies]
  tag = "tags"

ここでは tags という分類を使う設定になっています。 tag (単数形) の方は気にしなくて良いです。(テーマの作成には出てこない…はず)

これにより、Hugo は「tags という taxonomy があり、taxonomy.html では、それがとりうる値 (値として何があるかはこの時点ではまだ分からない) を列挙するべき」ということを認識できます。

分類値 (term)

一方で、その分類で管理したいコンテンツのフロントマターには tags を記載しておきます。

1
2
3
4
5
6
---
title: "Hugo テーマ 2. 作られたファイル"
date: 2026-05-23T00:00:00+09:00
tags:
    - "hugo"
---

これで、Hugo は「tags には hugo という値がある。taxonomy.html では値 hugo (値はほかにもあるかもしれない) を出力する」ことを認識します。

そして同時に「term.html では tagshugo という値を含むコンテンツを列挙するべき」と認識します。

まとめると

以下のようになります。

記述する場所Hugo での扱い例: このサイトでの出力結果 (URL)
分類 tagsconfig.toml[taxonomies]taxonomy.htmlhugo などの値を列挙する/tags/
分類値 hugoコンテンツのフロントマターterm.htmltags = ["hugo"] を持つページを列挙する/tags/hugo/

layouts/taxonomy.html

特定の分類 (例えば上記の tags) の分類値を列挙するレイアウトを定義します。

1
2
3
4
5
6
7
{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}
  {{ range .Pages }}
    <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
  {{ end }}
{{ end }}

ざっくり解説: 分類の .Title.Content とは?

分類や分類値についても、コンテンツと同様にタイトルやコンテンツを持てます。

content/  
  section1/
    content1-1.md
  section2/
    content2-1.md
  tags/
    _index.md   ← 分類 tags のコンテンツ
    hugo/
      _index.md ← 分類値 hugo のコンテンツ

たとえば content/tags/_index.md を以下のように記述します。

---
title: "tag です"
---

hello

これで、taxonomies.html にある .Title は “tags です” になり、.Content は “hello” になります。

より突っ込んで知りたい方へ

layouts/term.html

特定の分類 (例えば上記の tags) の、特定の分類値 (例えば上記の hugo) を持つページを列挙するレイアウトを定義します。

1
2
3
4
5
6
7
{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}
  {{ range .Pages }}
    <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
  {{ end }}
{{ end }}

ざっくり解説: 内容が taxonomy.html と変わらない

ざっくり解説: セクションもコンテンツもページで触れましたが、例に漏れず、taxonomy も term も Hugo のレイアウト定義上ではページとして扱われます。

なので、「なんらかのページを対象としており、かつその .Pages に何らかのページの集合があることが期待される」という構造が変わらないため、同じ内容になっていると思われます。
もちろん、これらはテーマ作成者の好きに変更してかまわないため、内容を違えても問題ありません。

余裕があれば、以下のようにファイルを書き換えると分かりやすいです。(確認が終わったら戻しましょう)

taxonomy.html, term.html ともに {{ .Kind }} を入れてページの種類を表示してみる:

1
2
3
4
5
6
7
{{ define "main" }}
  <h1>{{ .Title }} | {{ .Kind }}</h1>
  {{ .Content }}
  {{ range .Pages }}
    <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> | {{ .Kind }}</h2>
  {{ end }}
{{ end }}

layouts/_partials/

_partials には、ページの構成要素となる構造を置いておきます。

baseof.html が参照しているもののうち、head.html を取り上げます。

再掲: baseof.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="{{ site.Language.Locale }}" dir="{{ or site.Language.Direction `ltr` }}">
<head>
  {{ partial "head.html" . }}
</head>
<body>
  <header>
    {{ partial "header.html" . }}
  </header>
  <main>
    {{ block "main" . }}{{ end }}
  </main>
  <footer>
    {{ partial "footer.html" . }}
  </footer>
</body>
</html>

layouts/_partials/head.html

1
2
3
4
5
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>{{ if .IsHome }}{{ site.Title }}{{ else }}{{ printf "%s | %s" .Title site.Title }}{{ end }}</title>
{{ partialCached "head/css.html" . }}
{{ partialCached "head/js.html" . }}