ブログをリニューアルした
ブログのデザインを刷新し、 Next.js から Astro 5 へ移行した。移行の動機、技術スタック、 v0 と Claude Code を活用したブログ構築の進め方について記す。
Vercel, the Vercel design, Next.js and related marks, designs and logos are trademarks or registered trademarks of Vercel, Inc. or its affiliates in the US and other countries.
このブログを Next.js から Astro に移行した。デザインの刷新が主な目的だったが、合わせてフレームワークやホスティング先も見直した。この記事では移行の動機、技術選定、そして v0 と Claude Code を活用したブログ構築の進め方について記す。
なぜ移行したか
最大の理由はデザインの刷新だ。旧ブログは Next.js の公式ブログテンプレート blog-starter-typescript をベースにしていた。内部的には細かな改良は行なっていたが、デザインに関しては自分のスキルがボトルネックでほとんど手付かずのままだった。 AI を使ったデザイン生成が実用的になってきた現在なら何とかなるだろうと考え、デザインの刷新に取り組むことを決めた。
Next.js 以外のメタフレームワークを使ってみたかったというのも理由の1つだ。このブログは SSG (Static Site Generation) で静的サイトとして配信されている。 Next.js のようなフルスタックフレームワークを使わず、 SSG に特化したフレームワークを使う選択肢もあるのではないかと少し前から考えていた。
技術スタック
移行後の技術スタックは以下の通り。
| カテゴリ | 技術 |
|---|---|
| メタフレームワーク | Astro 5 (SSG) |
| UI フレームワーク | React 19 (インタラクティブなコンポーネントのみ) |
| スタイリング | Tailwind CSS 4 + @tailwindcss/typography |
| UI コンポーネント | shadcn/ui + Radix UI |
| コンテンツ | MDX via @astrojs/mdx |
| フォント | Noto Sans JP / Zen Maru Gothic / JetBrains Mono |
| ホスティング | Cloudflare Workers (Static Assets) |
| パッケージマネージャ | pnpm 10 |
メタフレームワーク
メタフレームワークには Astro を選んだ。 Astro はコンテンツ重視のサイトに特化しており、デフォルトで JavaScript をクライアントに送らないアーキテクチャを採用している。 Content Collections という機能で MDX を型安全に管理することもできる。ブログのような静的コンテンツが主体のサイトとは相性が良い。
とまあお手本のような説明を書いてみたが、他のフレームワークとの比較検討には正直そこまで力を入れたわけではない。以前 Gatsby から Next.js に移行した経験から、個人ブログのサイズ感であればフレームワークの移行はそれほど不可逆性の高い作業にはならないと分かっていたので、もし他のフレームワークに移りたくなっても大きな技術的負債にはならないだろうと判断した。
UI フレームワーク
動的な UI コンポーネントには React を選んだ。 Svelte も候補として検討したが、後述する v0 でのコード生成や MDX との相性が確認できなかったことから、今後しばらくは他ツールとの相性でつまずく可能性が高いと考え、今回は見送った。
なお、静的な UI コンポーネントには Astro コンポーネントを使用している。
ホスティング
デプロイ先には Cloudflare Workers (+ Static Assets) を選んだ。元々 Vercel を使っており、特に不満はなかったが、同一プラットフォーム上で旧ブログと新ブログを並行運用しながら移行するのが面倒そうだった。また、ドメインは元々 Cloudflare で管理していたので、ホスティングも Cloudflare に統一してしまった方が管理が楽だと考えた。
リニューアル作業
今回のブログ構築は、まず v0 を使ってデザインを作成し、それを参考に Claude Code にブログ全体を改めて構築させ、最後に Cloudflare Workers にデプロイするという手順で作業を行なった。
v0 でブログのデザインを作成
最初から Claude Code で実装しなかったのは、単に v0 を一度使ってみたかったというのと、 Claude Code のみで生成されたコードについてデザイン面で課題を感じたからだ。
両者の比較のために v0 (v0 Max) と Claude Code (Opus 4.6) に同じプロンプトを与えてどんなデザイン、コードが出来上がるのか比較してみた。なお、 v0 は英語プロンプトの方が精度が高いという情報があったため、今回のプロンプトも英語にしている。
プロンプト
Create a modern, minimal blog template using **TypeScript, Astro, Tailwind CSS, and shadcn/ui**.
**Pages & Layout:**
- Homepage with a hero section and a grid of article cards (thumbnail, title, date, tags)
- Article page with a table of contents sidebar, author bio, and share buttons
- Dark mode toggle in the header
- Responsive design (mobile-first)
**Design & Color:**
- Color palette: black and white base with an icy blue accent inspired by Antarctica — think glacial blues (#0EA5E9 or similar)
- Clean, high-contrast aesthetic with generous whitespace
**Typography:**
- Use `@tailwindcss/typography` plugin for article prose styling
- Clean, readable typographic hierarchy inspired by Medium/Notion
**Tech notes:**
- Use Astro's content collections for blog posts
- Integrate `@astrojs/react` to enable shadcn/ui (React-based) components within Astro
- Leverage shadcn/ui components for interactive UI elements (buttons, cards, navigation, dark mode toggle, etc.)
- Use Astro components (`.astro`) for static layout and pages, and React components (`.tsx`) only where shadcn/ui or client-side interactivity is needed
- All code should be written in TypeScriptv0 が生成したブログのスクリーンショットは以下の通り。
Claude Code が生成したブログのスクリーンショットは以下の通り。
v0 は色やフォントの使い方がうまく、デザインの完成度が高かった。一方で、生成されたコードには技術的に修正が必要な箇所が多かった。定量的には、 Claude Code の /pr-review-toolkit プラグインによるレビューで、 v0 が生成したコードに対しては Claude Code が生成したコードよりも2倍近く多くの問題が検出された。逆に Claude Code は技術的な問題点が少ないものの、デザイン的には無難でいまひとつな印象を受けた。このため、 v0 で作成したデザインを参考資料として Claude Code に渡し、 Claude Code でコードを生成するという方針に落ち着いた。
Claude Code でブログ構築
v0 のデザインを参考にしつつ、 Claude Code にブログ全体の構築を指示した。プロンプトの叩き台を Claude Code で作成した上で、自分が加筆・修正している。
Claude Code に与えたプロンプト
# ブログリニューアル: プロジェクトセットアップ
## 概要
個人ブログ(hamakou108.com)をリニューアルする。既存ブログのソースコード (`my-blog-nextjs`) を `/add-dir` でコンテキストに含めているので参照すること。
## 技術スタック
- **メタフレームワーク**: Astro
- **UI フレームワーク**: React(`@astrojs/react` を利用)
- **スタイリング**: Tailwind CSS + `@tailwindcss/typography`
- **記事フォーマット**: MDX(Astro の Content Collections を利用)
- **コンポーネントライブラリ**: shadcn/ui
- **パッケージマネージャ**: pnpm
- **デプロイ先**: Cloudflare Pages(SSG のみ。アダプタは不要で `astro build` の出力をそのままデプロイする)
パッケージは最新版を利用すること。
## デザイン方針
- 技術ブログらしくシンプルで読みやすいデザイン
- 日本語に適したフォント
- ダークモード対応(システム設定に追従 + トグルで切り替え可能)
- レスポンシブ対応(モバイルファースト)
- shadcn/ui のコンポーネントを活用して統一感のある UI にする
- 配色は shadcn/ui のデフォルトテーマをベースに調整
事前に v0 でレイアウトやUIコンポーネントを生成して `v0-sample/` に配置してあるので、デザインの参考にすること。ただし、パッケージのインストールやフレームワークのセットアップはあくまで後述する指示やベストプラクティスに則って実施し、このサンプルの利用はコンポーネントや CSS スタイルの作成時に参考資料とする程度に留めること。このサンプルの技術的な正確性は担保されていない。
なお、既存ブログのデザインは基本的には参考にする必要はない。
## やること
### 1. プロジェクトの初期構築
- 上記の技術スタックで Astro プロジェクトを新規作成する
- Tailwind CSS のセットアップ
- shadcn/ui のセットアップ
- TypeScript の設定(strict モード)
- ESLint, Stylelint, Prettier の設定(Astro 対応を含む)
過去の知識に頼らず、ドキュメント等を参照して現在のセットアップ方法を理解して行うこと。
### 2. レイアウト・ページの作成
以下のページ・レイアウトを作成する。デザインの方針は後述の「デザイン方針」セクションを参照。v0 で事前に生成したコードがある場合はそれをベースに組み込むこと。
レイアウト:
- ベースレイアウト(<html>, <head>, メタタグ, OGP 設定)
- ヘッダー(サイト名、ナビゲーション)
- フッター
ページ:
- トップページ(記事一覧)
- 記事詳細ページ
- (あれば)About ページ
- プライバシーポリシー (既存ブログを参照)
### 3. 記事まわりの構築
- Astro Content Collections で MDX 記事を管理する
- 既存ブログの MDX 記事のフロントマター構造を踏襲する (新要素があれば追加しても良い)
- 既存ブログの React カスタムコンポーネントを Astro + React の構成に合わせて移行する。既存コードを参照し、必要に応じてリファクタリングすること(Next.js 固有の API への依存を除去する等)
- 既存ブログで使われている rehype / remark プラグイン(rehype-starry-night 等)の設定を移行する
### 4. 既存記事の移行
既存ブログから記事をすべてコピーして新リポジトリに配置する
## 注意事項
- 既存ブログで Next.js 固有の機能(next/image, next/link, next-mdx-remote 等)に依存している部分は Astro / React の仕組みに置き換える
- Sass は使わない(Tailwind CSS v4 + ネイティブ CSS nesting で代替する)
- pnpm, Renovate, Secretlint といったツール系の設定も移植し、必要があれば内容を調整する
- GitHub Actions のワークフローも移植し、必要があれば内容を調整する
- 段階的に作業を進め、各ステップで動作確認できる状態を保つこと品質保証は Claude Code の /pr-review-toolkit によるレビュー、設定ファイルやレイアウトファイルなどの主要ファイルに対する人間のコードレビュー、ブラウザでの動作確認等を通して行なった。生成されたすべてのコードに目を通したわけではない。特に UI コンポーネント系のコードはほとんど見ていない。
初期コードの完成度は想像以上に高く、細かな問題点も AI によるレビューで一定発見することができたが、人間の目によるチェックを完全に外すまでには至らなかった。以下のような問題を手動で発見・修正している。
- About ページが自動生成されており、事実と異なる自己紹介が記載されている
- ライトモード表示時に一部の文字色が白になり、背景と同化して見えなくなる
- トップページや記事一覧ページのみ OGP 画像が設定されない
- ブログ内リンクが絶対パスになっており、プレビュー環境でも本番環境の URL が表示される
後は魅力品質に当たるような細かいデザインやコンテンツの調整を行い、実装を完了した。
Cloudflare Workers へのデプロイ
最近の Cloudflare は Pages よりも Workers による静的アセットの配信の方を推している 1 ようで、自分もそれに従った。
Cloudflare には Git 連携機能がある。リポジトリとビルドコマンドを指定すれば、 PR 作成時にプレビュー環境へ、 PR マージ時に本番環境へ自動でデプロイされるようになる。この仕組みは Vercel と同様で、特に迷うことなく設定できた。
ドメイン設定では Workers のカスタムドメインを追加する必要があったが、 Vercel 向きだった既存の DNS レコードが残っていると設定できなかったため、まずこれを削除した。その上でカスタムドメインを追加すると自動的に DNS レコードが作成された。 www ありのドメインも追加したかったので、 Domains > Rules から Redirect from WWW to root テンプレートを使ってリダイレクトルールを作成し、作成時に表示されるダイアログから www の A レコードも作成した。
終わりに
デザインは素人だが、 v0 と Claude Code の力を借りることでデザイン刷新を完遂できた。
移行に伴っていくつかの技術的負債が解消できたのも良かった。例えば、旧ブログでは Sass を使っていたが、 CSS のみの構成に置き換えられた。また、元々自分では気づいていなかったが、EXIF データのチェックスクリプトの検知対象キーに漏れがあり、その問題も移行をきっかけに修正できた。
Gatsby から Next.js への移行、 Next.js から Astro への移行と、このブログは自分のフレームワーク遍歴の生き証人のようになっている。次の移行がいつになるかは分からないが、その頃には人間がコードを1行も読むことなく AI が最初から最後までやってくれてそうだなと感じる。