Hugo(SSG)をやってみた

Hugoをやってみた

The world's fastest framework for building websites
Hugo is one of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again.
The world's fastest framework for building websites favicon https://gohugo.io/
The world's fastest framework for building websites

まずインストールから。aptでインストールされるのは古いHugoだったりするのでsnapでインストール。他のSSGと違って単体で動作するのは強み。

インストール

sudo snap install hugo

サイトを作成する

hugo new site hugoblogcd hugoblog

テーマをgit submoduleでインストール

git initgit submodule add https://github.com/theNewDynamic/gohugo-theme-ananke themes/ananke

テーマがページネーションやポストのレイアウトをしてくれるので自作しなくても済むもののテーマに合わせないといけないのでなにか変えようとすると大変(後述)

しかしながら一から作るよりは絶対にラクではある。

hugoの設定は/hugo.tomlや/config.tomlなどのファイルに記述する。

mdxファイルがAstroの記事には混ざっているので暫定的にmdとして扱う。

11tyと同じようにblog以下の記事はサイトのルートに配置されるのでpermalinksで変更する。

hugo.toml に設定を書く

/hugo.toml
baseURL = "http://ubanis.com/"languageCode = "ja"languageName = "Japanese"defaultContentLanguage = "ja"hasCJKLanguage = truetitle = "へび右曲がり"theme = "ananke"[params]  text_color = "dark-gray"  background_color_class = "bg-navy"  favicon = "/images/hebi.png"  ShowFullTextinRSS = false  [params.author]    name = "ubanis.com(Web)"    url = "https://ubanis.com"    photo = "/img/nyan4.jpg"# タグの URLパスは /tags/ になる[taxonomies]  tag = "tags"# mdxもmdファイルとして扱う[mediaTypes]  [mediaTypes."text/markdown"]    suffixes = ["md", "markdown", "mdx"]# blog はルート直下に配置[permalinks]  blog = "/:sections[1:]/:filename/"[[menu.main]]identifier = "about"name = "about"url = "/profile/"weight = 20[[menu.main]]identifier = "blog"name = "blog"url = "/blog/"weight = 30[[menu.main]]identifier = "tags"name = "tags"url = "/tags/"weight = 40

サイトのコンテンツは/content以下に配置する。_index.mdだとテーマが記事のリストを下に追加する。

/content/_index.md
---description: "テスト用"---# Hugo のテストブログHugoのテストです

blogのセクションにはセクションごとの_index.mdを置く。これにテーマのテンプレートが適用される。以下のページはこの下にテーマのlist.htmlがテンプレートになり記事一覧が入ることになる。

/content/blog/_index.md
---title: "記事一覧"---## 最近の記事一覧

サブディレクトリもある場合はサブディレクトリにもとりあえず_index.mdを置かないとhugo.yamlにあったsection配列のスライスが正しく動作しなかった。理由はよくわからないがとりあえず設置。

/content/blog/2025/_index.md の例
---title: "hugo problem?"draft: true---

レイアウトの修正

Astroでいうpublicフォルダは/staticにあたるのでここに画像などを配置する。画像最適化をする場合は変更が必要。

テーマのレイアウトを変更する必要がある場合は /_layouts/_default以下に修正したhtmlや変更箇所の記述が必要。

以下のlist.htmlはテーマのlist.htmlをコピーしたものを改変したもの。記事の一覧表示の部分をサブディレクトリまで探索するように変更したもの。セクションのディレクトリごとに_index.mdがあるとサブディレクトリ以下の記事は一覧に表示されないため。(テーマの挙動)

/layouts/_default/list.html
{{ define "main" }}<article class="pa3 pa4-ns nested-copy-line-height">  <section class="cf ph3 ph5-l pv3 pv4-l f4 tc-l center measure-wide lh-copy nested-links {{ $.Param " text_color" |    compare.Default "mid-gray" }}">    {{- .Content -}}  </section>  <section class="flex-ns mt5 flex-wrap justify-around">    {{ $pages := where site.RegularPages "Section" .Section }}    {{ $paginator := .Paginate $pages }}    {{ range $paginator.Pages }}    <div class="w-100 w-30-l mb4 relative bg-white">      {{ .Render "summary" }}    </div>    {{ end }}  </section>  {{- template "_internal/pagination.html" . -}}</article>{{ end }}

記事ページのテンプレート bridgy-fedのためにテンプレートの変更が必要。テーマからsingle.htmlを持ってきて改変して設置。

/layouts/_default/single.html
{{ define "main" }}<div id=#blogbody class="flex-l mt2 m8 center">  <article class="center cf pv5 ph3 ph4-ns mw7">        {{ with .Params.tags }}          <div class="tags-container">            {{ $taxonomyName := "tags" }}            {{ $taxonomyMap := index $.Site.Taxonomies $taxonomyName }}            {{ if $taxonomyMap }}              {{ range . }}                {{ $tagName := . }}                {{ $tagPageData := index $taxonomyMap $tagName }}                {{ if $tagPageData }}                  <a href="{{ $tagPageData.Page.Permalink }}" class="p-category" rel="tag">{{ $tagName }}</a>                {{ else }}                  <span class="p-category">{{ $tagName }}</span>                  <span style="color:orange; font-size:small;">(Link not found for '{{ $tagName }}')</span>                {{ end }}              {{ end }}            {{ else }}              <span style="color:red; font-size:small;">Taxonomy '{{ $taxonomyName }}' not found. Check config.toml.</span>            {{ end }}          </div>        {{ end }}    <div class="h-entry">      {{ if .Params.isPname }}        <p class="p-name hidden">{{ .Title }}</p>      {{ end }}      <section class="e-content">        <div class="nested-coply-line-height lh-copy f4 nested-links  {{ $.Param "text_color" | compare.Default "mid-gray" }}">        {{ .Content }}      </section>      {{ with .Params.replyTo }}        <div class="reply-container">          <a href="{{ . }}" class="u-in-reply-to">            リプライ先          </a>        </div>      {{ end }}      <div class="hidden" style="display:none">        {{ with .Site.Params.author }}          <a rel="author" class="p-author h-card" href="{{ .url | absURL }}">            {{ .name }}            {{ with .photo }}              <img class="u-photo" src="{{ . | absURL }}" alt="{{ $.Site.Params.author.name }}" />            {{ end }}          </a>        {{ end }}        <a class="u-url" href="{{ .Permalink }}">固定リンク</a>        <a class="u-bridgy-fed" href="https://fed.brid.gy/"></a>        <a href="https://brid.gy/publish/bluesky"></a>        {{ with .Date }}          <time class="dt-published" datetime="{{ .Format "2006-01-02T15:04:05Z07:00" }}">            {{ .Format "2006-01-02T15:04:05Z07:00" }}          </time>        {{ end }}        {{ with .Params.tags }}          <div class="tags-container">            {{ $taxonomyName := "tags" }}            {{ $taxonomyMap := index $.Site.Taxonomies $taxonomyName }}            {{ if $taxonomyMap }}              {{ range . }}                {{ $tagName := . }}                {{ $tagPageData := index $taxonomyMap $tagName }}                {{ if $tagPageData }}                  <a href="{{ $tagPageData.Page.Permalink }}" class="p-category" rel="tag">{{ $tagName }}</a>                {{ else }}                  <span class="p-category">{{ $tagName }}</span>                  <span style="color:orange; font-size:small;">(Link not found for '{{ $tagName }}')</span>                {{ end }}              {{ end }}            {{ else }}              <span style="color:red; font-size:small;">Taxonomy '{{ $taxonomyName }}' not found. Check config.toml.</span>            {{ end }}          </div>        {{ end }}      </div>    </div>  </article></div>{{ end }}

partials で head タグの内容を追加

<head>にタグを追加するために/layouts/partialsディレクトリを作成してhead-additions.htmlを作成する。これをテンプレートが読み込み<head>内に挿入する。

/layouts/partials/head-additions.html
  <meta property="og:image" content="{{ $.Site.Params.OgImage }}" />   <meta property="twitter:creator" content="{{ $.Site.Params.Twitter}}" />  <meta name="google-site-verification" content="{{ $.Site.Params.SiteVerify}}" />   <!--  省略 -->

/layouts/_default/以下に_markupディレクトリを作成してrender-image.htmlを配置。記事内のimgタグにu-photoクラスを付けるよう

/layouts/_default/_markup/render-image.html
<img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" class="u-photo" {{ with .Title }} title="{{ . }}"{{ end }} />

記事をビルドして表示してみる。(必ずhugo.yamlなどの設定ファイルがあるルートディレクトリで行わないと設定ファイルが見つからずエラーとなる)

hugo buildhugo server

hugo

Hugoの結論

11tyよりはなんとなくやりやすいもののそれはテーマのおかげなため自分でいろいろ変えようとするとこちらのほうが大変そうではある。

画像最適化やカスタマイズは後からやってみたものの厄介に感じた。もっと調べればベストな方法は見つかるかもしれない。