アカベコマイリ

HEAR NOTHING SEE NOTHING SAY NOTHING

サイト実装を GatsbyJS から Astro へ移行

このサイトの実装を GatsbyJS から Astro へ移行した。

更新停滞

これまでサイト実装を WordPress、GatsbyJS と変遷してきた。GatsbyJS は 2019 年当時、React + Markdown な点を気に入って採用したのだが、以下の理由から運用の厳しさを感じていた。

  • TypeScript 移行
  • プラグイン管理
  • GraphQL 管理

もともと TypeScript なしで導入したので我慢していたが、静的型チェックに慣れた身としては素の JavaScript は厳しすぎる。プラグインと GraphQL 管理も型チェックに頼れないと辛い。

そこで代替に Astro を検討したのだが、GatsbyJS で構築したサイトを移行するには作業量が膨大である。いちおう着手はした。しかし実験リポジトリーを用意して、ブログのサンプルを手動で現行サイトに近づけて、…としているうちに今後の予測される作業量にくじけてしまった。

そのままずるずると数年。サイト更新は停滞した。

Claude Code

2026 年。AI コーディングエージェント導入に懐疑的だった私でも、実用十分に感じられる時代となった。これまで微妙な AI 生成コードの後始末をする機会が多く、印象はよくなかった。しかし 2025 年の後半ぐらいから品質はめざましく向上した。特に目的の明確なこと、例えば既存実装で採用しているライブラリーやフレームワークの移行などは相当の精度で実現してくれる。

例えば以下の PR は remark という Markdown 処理ライブラリーについて、破壊的な変更へ対応しながらバージョン更新している。これは人間が実装するには学習と作業コストが重過ぎて何年も足踏みしていたものだ。これを Claude Code はプランも含め、40 分ぐらいで生成してくれた。

この事例を契機に AI コーディングエージェント慣れのため、Claude Code でサイト実装の移行を試すことにした。

移行

いきなり現行サイトを移行するのは危ないので、すでに用意していた Astro 用の実験リポジトリーを利用する。Claude Code 向けに 2 種類の仕様書を用意した。

ひとつめはトップ ページ。

# トップページ仕様

https://akabeko.me/ を踏襲します。

## Header

- 外部サービスのリンク
  - GitHub
    - https://github.com/akabekobeko
  - X
    - https://x.com/akabekobeko
  - Instagram
    - https://www.instagram.com/akabekobeko/
- サイト名
  - akabeko.me
- サブタイトル
  - HEAR NOTHING SEE NOTHING SAY NOTHING

## Content

- ABOUT
  - サイト概要ページへのリンク
  - about/
- BLOG
  - ブログのトップへのリンク
  - blog/
- SERIES
  - シリーズ記事まとめへのリンク
  - series/
- MEMO
  - メモ記事まとめへのリンク
  - memo/

## Footer

`Copyright © 2009 - 2026 akabeko.me All Rights Reserved.` を表示

ふたつめは記事仕様。

# 記事仕様

src/pages 配下の Markdown 仕様です。

## 記事のファイル構成

ブログ記事は `src/pages/blog/yyyy/MM/dd.md` として作成します。

- yyyy
  - 4 桁の年 (西暦)
  - 例えば `2026`
- MM
  - 2 桁の月
  - ゼロ詰めで `01` から最大 `12` まで
- dd.md
  - 記事となる Markdown ファイル
  - 2 桁の日
  - ゼロ詰めで `01.md` から最大 `31.md` まで

記事に表示する画像は以下となります。

- 記事と同じディレクトリー内に併置
- 記事と同じファイル名で拡張子だけ変更
  - 記事 `25.md` で表示する PNG 画像なら `25.png`
  - 同じ拡張子のファイルが複数の場合は `25-1.png``25-2.png` のように `-N` 形式で連番を振る
- 記事からの参照は相対パスとする
  - 記事 `25.md` で表示する PNG 画像なら `![画像](25.png)`
- Astro で記事をビルドした HTML も相対パス参照を維持すること
  - 記事 `25.md` で表示する PNG 画像を `![画像](25.png)` とした場合、HTML リンクは `<img src="25.png" title="画像" alt="画像" />`

## Markdown

記事の Markdown は GFM (GitHub Flavored Markdown) とします。記事のメタデータは冒頭に Frontmatter として定義します。

```markdown
---
path: "/blog/2023/12/code-comment/"
date: "2023-12-20T00:00:00Z"
title: "コメント書くや書かざるや"
categories: ["開発"]
tags: ["プログラミング", "コメント"]
excerpt: "3-shake Advent Calendar 2023、20 日目の記事です。ソフトウェア開発のプログラミングにおける、コメントのあり方と書き方について。"
---

本文
```

Frontmatter は以下となります。

- path
  - 記事を Web サイトとして公開した際のパス
  - path が `/blog/2023/12/code-comment/` でサイトが `https://example.com` ならフルパスは `https://example.com/blog/2023/12/code-comment/` になる
- date
  - 記事の日時を ISO 8601 の UTC 形式で定義
  - 記事 HTML では年月日までを表示
  - 記事一覧の順番は date 降順とする
- title
  - 記事名
- categories
  - カテゴリー
  - 文字列配列として複数、定義可能
  - カテゴリー一覧からカテゴリーを選択した場合、それを categories に含む記事をだけを一覧表示する
- tags
  - タグ
  - 文字列配列として複数、定義可能
  - タグ一覧からタグを選択した場合、それを tags に含む記事をだけを一覧表示する
- excerpt
  - 記事概要
  - 記事一覧に表示するための短文

## 記事描画

記事 Markdown に対する Astro テンプレート構成は https://akabeko.me/blog/2023/12/code-comment/ を参考にしてください。

### Header と Footer

- 本プロジェクトの docs/specs/top.md と共通

### Content

- Header
  - title
    - Frontmatter の title
    - `<h1>` として出力
  - date
    - Frontmatter の date
    - ユーザー環境のロケールにあわせた年月日を表示する
    - Astro の SSG で難しければ en-US 固定でよい
  - categories
    - Frontmatter の categories
    - `categories/category` へリンクする
  - tags
    - Frontmatter の tags
    - `tags/tag` へリンクする

### Article

- GFM に基づいた HTML を出力。Astro 標準機能でよい。
- 記事の最下部に前後記事のリンクを表示
  - 前後記事は Frontmatter の date により決定
  - 前の記事は date が一つ古いもの
  - 後の記事は date が一つ新しいもの
  - これらは `<nav>` として出力

仕様書 Markdown ファイルをリポジトリーの docs/specs に保存しておき、Claude Code へ以下を指示した。

docs/specs の仕様書に基づき、サイトを実装してください。

生成コードとしては動作 9 割、外観 6 割の完成度で Astro 版サイトが生成された。このときは Claude Code Pro Max (x5) を契約して Opus 4.5 で実行したのだが、トークン消費は 10% 未満で生成も 10 分ぐらいだったと思う。

更なる機能実装や改修も、基本的に Claude Code で進行。例えば以下を対応した。

  • ブログ記事一覧をページネーション対応させてください
    • 10 記事単位でページ分割
    • 記事は Frontmatter の date で時系列降順
  • カテゴリーとタグのページを実装してください
    • それぞれ記事の Frontmatter の category、tags から生成
    • 属する記事を一覧表示
    • ページネーション対応、10 記事単位でページ分割
  • カテゴリーとタグの一覧ページを実装してください
    • それぞれ記事の Frontmatter の category、tags から生成
    • 属する記事の数も併記

対話形式により軌道修正も実施したが、Claude Code からの確認がおおむね的確で作業はスムーズだった。

ただし Tailwind CSS で無駄な指定が多かったのと、私自身のこだわりから外観は継続的に手直ししている。ここも Claude Code でいけそうだが、娯楽としてあえて手動対応とした。

Netlify 設定の変更

Astro は Netlify プラグインを提供している。しかしこれは利用せず、連携した GitHub リポジトリーの main push で Deploy する方式を踏襲することにした。

実験のため、Netlify に新規プロジェクトを追加して Astro 版リポジトリーと連携してみる。これと現行の GatsbyJS 版プロジェクトの設定を比較して差分変更する。

結果、Build settings の Publish directory だけ変更すればよいことがわかった。GatsbyJS は public、Astro は dist になる。

Netlify の Build settings で Publish directory を public から dist に変更

もう一点、現行の GatsbyJS プロジェクトでは Node.js バージョンを .nvmrc に定義していた。しかし実際は Netlify 側で設定する必要があるようで、そちらの古いバージョンが利用されていることに気づいた。

そのため移行にあわせて Netlify の Dependency management で Node を更新しておいた。

この状態で Astro 版の実装を現行サイトのリポジトリーへ上書きした PR を作成、Netlify preview も正常動作していたので main へ merge & push した。無事に Netlify の本番 Deploy も完了して、こちらも正常動作を確認できた。

akabeko.me 本番サイト

感無量。何年も更新停滞していたサイトが再始動した!うれしい!!