このサイトはHugo
で構築しています。
ベースはRobust
というテーマで、これをフォークしてrobust-iniwa
というリポジトリで管理し、各サイトからは Git submodule として取り込んでいます。
この記事では、2026年9月8日に当サイトが取り込んでいる robust-iniwa のソースを基に、主なカスタマイズと、それを支えるサイト側(このリポジトリ)の構成についてまとめます。
コードはどんどん変わるので、最新はGitHub
を見るのが早いです。この記事は雰囲気を掴む用です。
現在の構成
最初は「themes/robust 配下は触らず、/layouts/ に上書きファイルを置く」運用にしていましたが、姉妹サイト(diary.iniwach.com
)と共通の改造が増えてきたので、テーマ自体をフォークして共有することにしました。
iniwach.com/
├── config/
│ ├── development/config.toml
│ └── production/config.toml
├── content/
├── static/
└── themes/
└── robust-iniwa/ ← submodule (https://github.com/iniwa/hugo_theme_robust-iniwa)
├── archetypes/
├── assets/
├── layouts/
└── static/js/
主な指針は次の通り。
- テーマ全体に効くカスタマイズは
themes/robust-iniwa/に置き、両サイトで共有 - サイト固有のもの(記事、画像、
config.toml、static/robots.txtなど)はサイトのリポジトリに置く - 設定は
config/development/とconfig/production/で分割し、hugo serverと本番ビルドで使い分ける
robust-iniwa 側では、上流(dim0627/hugo_theme_robust)に対してファイル単位で [mod] [new] [removed] のコメントマーカーを付けて差分を追えるようにしています。
サイドバーの構成
Author / Archives / Tags / Latests / Memos(設定時のみ) の順で並べています。
themes/robust-iniwa/layouts/baseof.html でこの順に partial を呼び出している形です。
Author欄
Twitter(X)、YouTube、Twitch、メールへのリンクを並べています。以前使っていた Font Awesome の CDN 読み込みは廃止し、現在はローカルのインライン SVG partial でアイコンを表示します。
config.toml の [params.author] を埋めるとそのまま反映されます。
|
|
サイドバーのアイコン部分は themes/robust-iniwa/layouts/_partials/author.html で、ローカルの SVG アイコンとともに mail/Twitch/YouTube 等のエントリを表示しています。
月別アーカイブ・Tags
Taxonomy
で、archive と tag の2つを定義。Categories は使わなくなったので消しました。
|
|
各記事のフロントマターで下のように書けば、勝手に年月別アーカイブが生成されます。
archives:
- 2025-02
サイドバー描画用に themes/robust-iniwa/layouts/_partials/archives.html を新規作成し、上流の taxonomy.html を流用する形にしています。
Latests
最新記事一覧。上流は10件固定だったので、Site.Params.latests_count で件数を可変にしました。未設定なら50件です。
[params]
latests_count = 50
Memos(自前ホスティングのメモ連携)
別途立てている Memos
サーバーから最新メモを取ってきて、サイドバーに表示するようにしました。
Site.Params.memos_url を設定したときだけ partial が描画されます。
外部スクリプト(marked, DOMPurify)はバージョン固定 + SRI ハッシュ付きで読み込み、サニタイズしてから描画しています。
実際の読み込みタグは themes/robust-iniwa/layouts/_partials/memos.html にあります。バージョンと integrity は対で管理し、更新時には取得したファイルからハッシュを生成します。省略したハッシュをコピーするとブラウザが読み込みを拒否するため、ここではタグの例を省いています。
サイドバーの追従スクロール
PC 表示時はサイドバーが画面に追従するようにしています。
昔は custom.css に直書きしていましたが、今は themes/robust-iniwa/assets/css/layout.css に分離。スクロールバーは Webkit/IE/Firefox それぞれの方法で非表示にしています。
ヘッダーとフッター
スクロール連動でヘッダーを隠す
よく見るアレ。下スクロールでヘッダーが消え、上スクロールで再表示されます。
baseof.html 末尾に小さい JS、layout.css に .l-header.is-hidden の transform を仕込む構成です。
フッターとサイト内ナビゲーション
baseof.html の <footer> に /notice と /privacy へのリンクを追加。
それぞれ content/notice.md と content/privacy.md として用意しています。当サイト固有の layouts/baseof.html では、技術・ゲーム・運営者・お問い合わせへの導線と noindex の出力を追加しています。この上書きはテーマ更新時に元ファイルとの照合が必要です。
記事メタデータの取り扱い
更新日(Lastmod)の表示
summary.html と list.html の両方で、Date != Lastmod のときに更新アイコン付きで日付を出すようにしています。
日付アイコンもローカルの SVG を使います。記事の Lastmod は本文に変更があったときに更新します。
dateformat は Site.Params.dateformat で "2006/01/02" 形式に統一しています。
archetype
hugo new ○○.md で生成される雛形。サイトリポジトリ側の archetypes/default.md に置いてあります。
|
|
description は OGP 用に必須で入れる方針なので、空欄を最初から差し込んでいます。
OGP / Twitter Card / 構造化データ
当初は記事一覧ページにだけ手書きで OGP メタタグを追加していましたが、今はテーマ側で全ページ自動対応するようにしました。
themes/robust-iniwa/layouts/_partials/meta.html の主なポイント。
IsHome/IsPage/ その他で OGP の中身を出し分けdescriptionは frontmatter のdescription優先、なければSummaryを160文字で truncate- 記事画像は Page Bundles に対応(
Resources.GetMatchで記事フォルダ内の画像を解決) data/ogp_manifest.jsonがあれば事前生成された OGP 画像を優先し、画像の登録漏れはビルドエラーにする- manifest がない場合は、
og_worker_urlの Cloudflare Workers + Satori による動的生成、または記事画像へフォールバック - localhost / 127.0.0.1 の URL は Workers に渡せないので除外
動的生成へフォールバックする場合は、?title=...&bg=...&site=...&v=... で記事タイトルや背景画像、サイト名、Lastmod のキャッシュバスター を渡しています。
構造化データ(JSON-LD)
themes/robust-iniwa/layouts/_partials/single_json_ld.html で BlogPosting を出力。上流は NewsArticle でしたが、ブログ記事なら BlogPosting の方が適切です。
description / author / dateModified などひととおり整備しています。
アクセス解析・コメント・収益化
| 機能 | どこに書く | 状態 |
|---|---|---|
| Google Analytics | [services.googleAnalytics] |
本番ビルド時のみ計測(DEV 環境では無効) |
| Disqus | — | 現在のテーマでは廃止 |
| Umami | [params.umami] |
website_id を入れたときだけ計測スクリプト挿入 |
| Google AdSense | [params] adsense_client_id |
hugo.IsProduction のときだけ <head> に挿入 |
[params.umami] の構造はこんな感じ。
[params.umami]
website_id = "xxxxxxxx-..."
script_url = "https://(自前ドメイン)/script.js"
AdSense の <script> タグは meta.html の中で Site.Params.adsense_client_id と hugo.IsProduction を確認し、さらにページの no_ads: true で出力を抑制しています。開発環境では出力しません。当サイトでは免責事項・プライバシーポリシー・移転案内と、404・タグ・月別一覧を対象外にしています。
ショートコード
themes/robust-iniwa/layouts/_shortcodes/ に下記を入れています。
accordion
<details> を使った折りたたみ。
ここをクリックで展開できます。
{< accordion title="ここをクリックで展開" >}
ここに展開後の内容
{< /accordion >}
※実際はカッコは2つです。
img-view
画像をグリッドで並べる用。
{< img-view "a.jpg" "b.jpg" "c.jpg" >}
{< img-view 2 "wide1.jpg" "wide2.jpg" >}
先頭に数値を入れると列数を指定できる(デフォルト3列)ようにしてあります。WebP サムネを自動生成して <picture> で出すので、フルサイズ原本は別ロードされません。
tip
ホバー / フォーカスでツールチップを出す注釈。
これは {< tip "ここにポップアップ文" >}対象テキスト{< /tip >} です。
スタイルは assets/css/tip.css、開閉ロジックは static/js/tooltip.js。
外部リンク
新しいタブで開く + アフィリエイト sponsored 自動付与
themes/robust-iniwa/layouts/_markup/render-link.html で Markdown のリンクをカスタムレンダー。
http(s)://で始まるリンクはtarget="_blank" rel="noopener"を付与- Amazon・楽天・e☆イヤホン・A8・LinkSynergy 等のアフィリエイト系ドメインを含む場合は
rel="sponsored noopener"に切り替え(Googleガイドライン準拠)
<a href="..." rel="sponsored noopener" target="_blank">...</a>
ドメイン一覧は配列で持っているので、必要に応じて足せます。
CSS の管理
昔は \layouts\partials\custom.css に全部詰めていましたが、テーマフォーク後にファイル分割しました。
assets/css/variables.css… カラー変数とサイズ。テーマバリアント切替もここassets/css/layout.css… ヘッダー・サイドバー・フッターと全体レイアウトassets/css/content.css… 記事本文の見出し・段落・コードブロック・accordion などassets/css/pagination.css… ページネーションassets/css/grid.css…img-viewのグリッドassets/css/tip.css… ツールチップassets/css/memos-style.css… Memos サイドバー用
テーマバリアント
baseof.html の <body data-theme="..."> 属性に Site.Params.theme_variant を入れていて、variables.css で [data-theme="garden"] / [data-theme="tech"] ごとに変数値を上書きしています。
このサイトは tech、姉妹サイトの diary は garden です。
[params]
theme_variant = "tech" # or "garden"
SyntaxHighlight・コードブロック
config.toml の [markup.highlight] で Hugo 内蔵の Chroma を使う設定にしています。
|
|
記事内では Markdown 記法でそのまま書けます。
```text {linenos=true,hl_lines=[1,"3-4"],linenostart=1}
ここにコードを記入
ハイライト指定や行番号開始位置を渡せる
```
詳細はHugoのドキュメント へ。
robots.txt と sitemap.xml
現在は、下書き用のパスをクロール対象から外すために、enableRobotsTXT = false にして自前の static/robots.txt を使う構成にしました。
User-agent: *
Disallow: /_draft/
Sitemap: https://iniwach.com/sitemap.xml
タグ・アーカイブ等には noindex, follow を出力し、検索エンジンがそれを読めるよう robots.txt ではブロックしません。
sitemap からはタグ・アーカイブ・カテゴリ・下書き等を除外するため、themes/robust-iniwa/layouts/sitemap.xml で Permalink をフィルタする独自テンプレートに差し替え。
{{ range .Data.Pages }}
{{ if or (in .Permalink "/tags/") (in .Permalink "/categories/") (in .Permalink "/archives/") (in .Permalink "/_draft/")}}
{{ else }}
<url>
<loc>{{ .Permalink }}</loc>
...
</url>
{{ end }}
{{ end }}
404ページ
上流の 404 はタイトルだけなので拡張。「トップへ戻る」リンクと最新記事5件を表示するようにしています。
themes/robust-iniwa/layouts/404.html 。
おわりに
最初は「themes 配下を触らない」運用でしたが、姉妹サイトとの共通化、上流との差分管理、デプロイ後のホットフィックスのしやすさ等を考えると、フォーク + submodule の方が圧倒的に楽でした。
hugo server で常にローカル確認しながら進められるのは引き続き気持ちいいです。AI を併用して書いていますが、上流との差分箇所には [mod] [new] [removed] のマーカーを残す運用にしているので、後から見返すときも比較的読みやすい状態を保てています。
更新履歴
- 2026/09/08
- 取り込み済みテーマのソースに合わせてパス、SVG、OGP、Disqusの説明を修正
- 当サイト固有のナビゲーションと広告・検索対象の扱いを追記
- 2025/02/06
- コードブロック書式の追加
- コンテンツの横幅についてを追加
- RSSフィードの対応
- 2025/02/07
- Robots.txtについて追加
- 2025/02/10
- ogpタグについて追加
- 記事一覧に更新日時の追加
- 2025/07/17
- リンクを新しいタブ開くを追加
- custom.cssを修正
- 2025/09/02
- 画像のグリッド表示を追加
- 2025/11/27
- custom.cssを更新
- ヘッダー追従の実装
- 2025/12/05
- テーマのサブモジュール化
- 2026/04/28
- 記事全体を現状の robust-iniwa の構成に合わせて全面リライト
- OGP(Page Bundles・Satori Workers連携)、JSON-LD、Memos、Umami、AdSense、tip ショートコード、テーマバリアント、CSS分割、外部リンクの sponsored 付与、404 ページ拡張などを追加
関連記事
参考にした記事
zzzmisa’s blog : HugoのテーマRobustのカスタマイズver3
syocky tech blog : Hugoテーマ「Robust」をカスタマイズする
親方の徒然なる日々 : HugoでFontAwesomeを使用してみた。
gkzz.dev : アコーディオンメニューをHugoで作った
テストウフ : Hugoのブログにページネーションを追加した
TelBouzu’s Blog : HugoのRobustでfaviconとかAdsenseの登録とか
OLD SUNSET DAYS : Hugoでrobots.txtとsitemap.xmlを作る
アロハル : HUGOでmeta descriptionなどのmetaタグを最適化する方法
k-kazがHugoで遊ぶサイト : Hugoで外部サイトを新しいタブで開きたい。
五里霧中 : GridレイアウトをCSSを利用したものに変更しました