🐟

Hugo+BlowfishなポートフォリオをGitHub Pagesにデプロイしよう!

2024/07/15に公開

始めに

ポートフォリオのソースはGitHubで管理しています。
https://github.com/zen96k/enoshima-escar
デプロイしたポートフォリオはこちらです。
https://zen96k.github.io/enoshima-escar

余談

いきなり余談を書くな。本当にすみません。
でも、ふざけていないと正気に戻って狂いそうになります。
「早く行きたいなら一人で行け、遠くに行きたいなら皆で行け。」
最近この言葉が気に入っています。上司の受け売りですが。
気になった技術を調査したり試したりして、記事を書いてアウトプットすることで、巡り巡って遠くに行けたら良いなと思っています。
嘘です、黙って俺に付いてこい。

動機

なぜポートフォリオか

自分のポートフォリオが欲しい!って思うことないですか?
僕はあります。気軽に備忘録とかを書ける場所が欲しいと思いました。

なぜHugo+Blowfishか

備忘録を書くだけならTwitterで良いじゃん。
QiitaとかZennとかNoteとかはてなブログで良くね?
これに関しては反論できません。
Hugo+Blowfishで作成されたポートフォリオを見つけて、かっこいいと思いました。

なぜGitHub Pagesか

Netlifyでも良いですが、今回はGitHub Actionsを触ってみたかったので、GitHub Pagesにデプロイすることにしました。
また、GitLabを自分で構築してPagesにデプロイしていたことがあったのですが、面倒くさくて辞めました。真っ当な人生を歩みます。

開発環境

Debian 12にDockerをインストールして、開発コンテナを使用しています。
開発コンテナは本当に素晴らしいです。DockerはRootlessモードで動作させています。

Hugoをインストールする

Hugoをインストールした開発コンテナを構築します。

dockerfileを作成する

dockerfile
FROM ubuntu:24.04

ARG DEBIAN_FRONTEND=noninteractive
ARG FASTFETCH_VERSION=2.18.1
ARG HUGO_VERSION=0.128.2

SHELL ["/usr/bin/bash", "-ecx"]

# ==============================
# Update apt config
# ==============================
RUN echo "APT::Install-Recommends false;" > /etc/apt/apt.conf.d/00-install-recommends && \
    echo "APT::Install-Suggests false;" > /etc/apt/apt.conf.d/00-install-suggests && \
    apt update

# ==============================
# Install packages
# ==============================
RUN apt install -y \
    ca-certificates \
    curl wget \
    git \
    tzdata \
    zip unzip \
    rsync

# ==============================
# Install fastfetch
# ==============================
RUN wget https://github.com/fastfetch-cli/fastfetch/releases/download/${FASTFETCH_VERSION}/fastfetch-linux-amd64.deb && \
    apt install -y ./fastfetch-linux-amd64.deb

# ==============================
# Install hugo
# ==============================
RUN wget https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_linux-amd64.deb && \
    apt install -y ./hugo_${HUGO_VERSION}_linux-amd64.deb

# ==============================
# Purge unused packages
# ==============================
RUN apt update && \
    apt full-upgrade -y && \
    apt autopurge -y && \
    apt autoclean && \
    rm -rf /var/lib/apt/lists

Hugoのインストール方法は公式サイトを参考にしました。
https://gohugo.io/installation/linux

GitHub ActionsのrunnerにはDebianを使用できず、Ubuntuを使用する関係で、開発コンテナでもUbuntuを使用します。
また、UbuntuでタイムゾーンをAsia/Tokyoに設定するために、tzdataをインストールします。

https://zenn.dev/k8shiro/articles/docker-image-timezone

devcontainer.jsonを作成する

devcontainer.json
{
  "build": {
    "dockerfile": "../dockerfile"
  },
  "runArgs": [
    "--name=ee-hugo"
  ],
  "containerEnv": {
    "TZ": "Asia/Tokyo"
  },
  "forwardPorts": [
    1313
  ],
  "customizations": {
    "vscode": {
      "extensions": [
        "eamodio.gitlens",
        "ms-azuretools.vscode-docker",
        "MS-CEINTL.vscode-language-pack-ja",
        "tamasfe.even-better-toml",
        "kennylong.kubernetes-yaml-formatter"
      ],
      "settings": {
        "editor.renderWhitespace": "all",
        "editor.tabSize": 2,
        "editor.formatOnSave": true,
        "files.trimFinalNewlines": true,
        "files.trimTrailingWhitespace": true,
        "[markdown]": {
          "editor.formatOnSave": false,
          "files.trimTrailingWhitespace": false
        }
      }
    }
  },
  "postStartCommand": "fastfetch"
}

devcontainer.jsonの仕様は公式サイトを参考にしました。
https://containers.dev/implementors/json_reference
開発コンテナのタイムゾーンをAsia/Tokyoに設定しています。
こうすることで、Hugoで作成する記事の公開日時が日本時間になります。

開発コンテナを起動する

VSCodeで開発コンテナを起動します。このような画面が表示されればOKです。

Hugoでプロジェクトを作成する

Quick startを参考にして、Hugoでプロジェクトを作成します。
開発コンテナでターミナルを開き、下記コマンドを実行します。

$ hugo new site . -f

-fオプションを付けることで、空のディレクトリでなくともHugoでプロジェクトを作成することができます。
※開発コンテナにはdockerfileなどが存在するため。

Blowfishをインストールする

Installationを参考にして、Blowfishをインストールします。
BlowfishにはBlowfish Toolsが用意されていますが、今回はGitのサブモジュールとしてインストールしました。
開発コンテナでターミナルを開き、下記コマンドを実行します。

$ git submodule add -b main https://github.com/nunocoracao/blowfish.git themes/blowfish

開発コンテナのワークスペースが大体このような状態になっていればOKです。

HugoとBlowfishを設定する

ConfigurationHugoで当ブログを作り直しました(Gatsbyから移行)を参考にして、HugoとBlowfishを設定します。

hugo.tomlを作成する

config/_default配下

hugo.toml
# -- Site Configuration --
# Refer to the theme docs for more details about each of these parameters.
# https://blowfish.page/docs/getting-started/

theme = "blowfish"
# baseURL = "https://your_domain.com/"
languageCode = "ja"
defaultContentLanguage = "ja"

[frontmatter]
date = [":fileModTime"]

[outputs]
home = ["HTML", "RSS", "JSON"]

dateに[":fileModTime"]を設定することで、Hugoで作成する記事の公開日時にファイルの保存日時が設定されます。
また、Hugoの検索機能を有効にするときは、homeに["HTML", "RSS", "JSON"]を設定する必要があります。

config/production配下

hugo.toml
# -- Site Configuration --
# Refer to the theme docs for more details about each of these parameters.
# https://blowfish.page/docs/getting-started/

baseURL = "https://zen96k.github.io/enoshima-escar"

開発環境で使用する設定をconfig/_default配下に作成して、本番環境で上書きしたい設定をconfig/production配下に作成します。

https://gohugo.io/getting-started/configuration

languages.ja.tomlを作成する

languages.ja.toml
languageCode = "ja"
languageName = "日本語"
title = "江ノ島エスカー"

[params]
displayName = "JA"
isoCode = "ja"
dateFormat = "2006年1月2日"

[author]
name = "Kotaro Kuroda"
image = "img/icon.jpg"
headline = "後藤正文になりたい"
links = [
  # { email = "mailto:hello@your_domain.com" },
  # { link = "https://link-to-some-website.com/" },
  # { amazon = "https://www.amazon.com/hz/wishlist/ls/wishlist-id" },
  # { apple = "https://www.apple.com" },
  # { blogger = "https://username.blogspot.com/" },
  # { bluesky = "https://bsky.app/profile/username" },
  # { codepen = "https://codepen.io/username" },
  # { dev = "https://dev.to/username" },
  # { discord = "https://discord.gg/invitecode" },
  # { dribbble = "https://dribbble.com/username" },
  # { facebook = "https://facebook.com/username" },
  # { flickr = "https://www.flickr.com/photos/username/" },
  # { foursquare = "https://foursquare.com/username" },
  { github = "https://github.com/zen96k" },
  # { gitlab = "https://gitlab.com/username" },
  # { google = "https://www.google.com/" },
  # { hashnode = "https://username.hashnode.dev" },
  { instagram = "https://instagram.com/zen96k" },
  # { itch-io = "https://username.itch.io" },
  # { keybase = "https://keybase.io/username" },
  # { kickstarter = "https://www.kickstarter.com/profile/username" },
  # { lastfm = "https://lastfm.com/user/username" },
  # { linkedin = "https://linkedin.com/in/username" },
  # { mastodon = "https://mastodon.instance/@username" },
  # { medium = "https://medium.com/username" },
  # { microsoft = "https://www.microsoft.com/" },
  # { orcid = "https://orcid.org/userid" },
  # { patreon = "https://www.patreon.com/username" },
  # { pinterest = "https://pinterest.com/username" },
  # { reddit = "https://reddit.com/user/username" },
  # { researchgate = "https://www.researchgate.net/profile/username" },
  # { slack = "https://workspace.url/team/userid" },
  # { snapchat = "https://snapchat.com/add/username" },
  # { soundcloud = "https://soundcloud.com/username" },
  # { stack-overflow = "https://stackoverflow.com/users/userid/username" },
  # { steam = "https://steamcommunity.com/profiles/userid" },
  # { telegram = "https://t.me/username" },
  # { threads = "https://www.threads.net/@username" },
  # { tiktok = "https://tiktok.com/@username" },
  # { tumblr = "https://username.tumblr.com" },
  # { twitch = "https://twitch.tv/username" },
  # { twitter = "https://twitter.com/username" },
  { x-twitter = "https://twitter.com/zen96k" },
  # { whatsapp = "https://wa.me/phone-number" },
  # { youtube = "https://youtube.com/username" },
  # { ko-fi = "https://ko-fi.com/username" },
  # { codeberg = "https://codeberg.org/username" },
]

dateFormatですが、これで日付のフォーマットだなんて信じられませんよね…。
https://ytyaru.hatenablog.com/entry/2022/10/31/000000

imageはassets配下に配置した画像ファイルを設定します。

menus.ja.toml
# -- Main Menu --
# The main menu is displayed in the header at the top of the page.
# Acceptable parameters are name, pageRef, page, url, title, weight.
#
# The simplest menu configuration is to provide:
#   name = The name to be displayed for this menu link
#   pageRef = The identifier of the page or section to link to
#
# By default the menu is ordered alphabetically. This can be
# overridden by providing a weight value. The menu will then be
# ordered by weight from lowest to highest.

[[main]]
name = "Posts"
pageRef = "posts"
weight = 10

# -- Footer Menu --
# The footer menu is displayed at the bottom of the page, just before
# the copyright notice. Configure as per the main menu above.

[[footer]]
name = "Tags"
pageRef = "tags"
weight = 10

[[footer]]
name = "Categories"
pageRef = "categories"
weight = 20

params.tomlを作成する

params.toml
# -- Theme Options --
# These options control how the theme functions and allow you to
# customise the display of your website.
#
# Refer to the theme docs for more details about each of these parameters.
# https://blowfish.page/docs/configuration/#theme-parameters

colorScheme = "blowfish"
defaultAppearance = "dark"
autoSwitchAppearance = false

enableSearch = true

defaultBackgroundImage = "img/background.jpg"

[homepage]
layout = "hero"
showRecent = true
# showMoreLink = true
cardView = true

[article]
showBreadcrumbs = true
showReadingTime = false
showTableOfContents = true
showWordCount = false
sharingLinks = ["twitter", "bluesky"]

defaultBackgroundImageはassets配下に配置した画像ファイルを設定します。

_index.mdを作成する

content配下

_index.md
SIerに勤務するクソ雑魚エンジニア  
絶望九州リージョン生まれ  
アジカン/BUMP/ガリレオが好き

<!-- {{< button href="/posts" target="_self" >}}
Posts
{{< /button >}} -->

{{< typeit
    speed=300
    tag=h3
    loop=true
>}}
波音の彼方に響く声 揺れるエスカー
{{< /typeit >}}

TypeItを使用することで、ホーム画面に色気を出すことができます。
https://blowfish.page/ja/docs/shortcodes

開発サーバーを起動する

Hugoの開発サーバーを起動して、ポートフォリオを確認します。
開発コンテナでターミナルを開き、下記コマンドを実行します。

$ hugo server -DEF --disableFastRender --gc

https://gohugo.io/commands/hugo_server

ポートフォリオが大体こんな感じで表示されていればOKです。

http://localhost:1313

Hugoで記事を作成する

linux-server-memo.mdを作成する

content/posts配下

linux-server-memo.md
+++
title = 'Linux Server Memo'
+++

自宅のPCにLinuxをインストールして、最初にやったことの備忘録。  
※ディストリビューションはDebian 12を使用した。

ポートフォリオが大体こんな感じで表示されていればOKです。

http://localhost:1313/posts/linux-server-memo

ワークフローを作成する

Hosting & DeploymentGitHub Actionsの書き方についてデバッグ設定、runs-onやcheckoutなどの仕組みや構造も含めて徹底解説を参考にして、GitHub Actionsのワークフローを作成します。

.github/workflows配下

deploy-portfolio.yml
name: Deploy Portfolio to GitHub Pages

on:
  push:
    branches:
    - work
    paths:
    - .github/workflows/deploy-portfolio.yml
    - archetypes/**
    - assets/**
    - config/**
    - content/**
    - themes/**

jobs:
  deploy-portfolio:
    runs-on: ubuntu-24.04
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: true
    env:
      TZ: Asia/Tokyo
    steps:
    - name: Checkout Source
      uses: actions/checkout@v4
      with:
        submodules: true
        fetch-depth: 0
    - name: Install Hugo
      uses: peaceiris/actions-hugo@v3
      with:
        hugo-version: 0.128.2
    - name: Build Portfolio
      run: hugo --minify --environment production
    - name: Deploy Portfolio
      uses: peaceiris/actions-gh-pages@v4
      if: ${{ github.ref == 'refs/heads/work' }}
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_branch: deploy
        publish_dir: ./public

workブランチにpushされたらワークフローが開始されるようになっています。
開発コンテナと同様に、環境変数TZにAsia/Tokyoを設定しています。
偉人たちが用意したジョブのテンプレートを使用して、楽をすることができます。
ビルドするときは、--environmentオプションで本番環境を設定しています。
アーティファクトの出力先はdeployブランチを設定しています。

ワークフローが成功して、deployブランチが自動で作成されていればOKです。

GitHub Pagesにデプロイする

ポートフォリオのリポジトリで、deployブランチからGitHub Pagesにデプロイするように設定します。

ワークフローが成功して、ポートフォリオがデプロイされていればOKです。


https://zen96k.github.io/enoshima-escar

終わりに

Hugo+BlowfishなポートフォリオをGitHub Pagesにデプロイすることができました。
リポジトリにpushしたら、自動でデプロイされるCI/CDパイプラインも構築できました。
なぜこの記事をポートフォリオで書かないのか、それはZennの方が記事を書きやすいからです。

また僕の業績評価が上がってしまうのか~~~😩😩😩

Discussion