---
title: "ブログを Claude Design × Claude Code で作り直した"
app: "yukyu.net"
author: "@yukyu30"
tags:
  - "Blog"
  - "Presonal"
  - "Nextra"
  - "Next.js"
tools:
  - "Claude"
website_url: "https://yukyu.net"
github_url: "https://github.com/yukyu30/yukyu-net"
---

yukyu.net は長らく Next.js Pages Router 時代に書いた v2 をだましだまし運用していたブログでした。今回、Claude Design でデザインを起こし、 Claude Code に引き継いで実装、最後にリポジトリ直下に昇格する、という流れで丸ごと作り直したので、その裏側を書きます。

---

## Chapter 1 — fly-by デザインシステムを Claude Design に渡す

最初のステップは「色とトーンの軸を Claude Design に共有する」ことでした。

普段の業務で触っている GMOペパボの共通基盤デザインシステム **inhouse**（プレフィックス `in-`）の設計思想を参考に、自分用に組み直した **fly-by**（プレフィックス `fb-`、メインカラーは深い青 `#002CED`）の repo をそのまま渡しました。

> You: 青色がメインのデザインシステム fly-by
> You: ブログをデザインをして

Claude Design は repo を辿って `tokens` や主要コンポーネントを読み、デザイン原則を要約してくれました。

確認できた前提：

- プライマリ: `#002CED`（深く強い青）
- 4px グリッドのスペーシング、`--level-*` のタイポスケール
- borderラジアスは控えめ（4px–8px）、白背景・グレー罫線中心の落ち着いた骨格

このトーンを「ブログ」という別ドメインに移し替えるとき、控えめな実用系のままにすると個人ブログとしては凡庸になります。骨格は守りつつ、見出しだけを大胆に振るという方針が自然と決まりました。

---

## Chapter 2 — 9 つのアートボードを並べて選ぶ

ヒアリングはこの 9 項目に答えるだけで済みました。

- blog_topic: 個人ブログ（雑多）
- pages_needed: 記事一覧 / 記事詳細 / カテゴリー
- vibe: エディトリアル・大胆なタイポグラフィ
- variations: はい、複数案を並べて比較したい
- imagery: 画像なし・テキストのみ
- density: 標準
- extras: 関連記事, 目次（記事内）
- language: 日本語
- site_name: yukyu.net

そこから Claude Design は **3 案 × 3 画面 = 9 アートボード** を一気に並べてくれました。

- **A. クラシック・エディトリアル** — Source Serif × 新聞的グリッド。文芸誌風の落ち着き。
- **B. スイス／グリッド** — Inter Tight × 巨大番号 × 罫線。索引としてのブログ。
- **C. ブルータル・モノタイポ** — JetBrains Mono × ターミナル比喩。技術系の人格。

並べて見ると判断は早く、こう返しました。

> You: index は B が好き
> You: c は article page と /reading のデザインが好き

> Claude: いい組み合わせですね。B のインデックス感と C のドキュメント美学を 1 つにまとめます。

「索引としての一覧 + ドキュメントとしての詳細」というハイブリッドが、ここで決まりました。fly-by の青はインデックスでナンバリング・アクセントに、 mono は詳細ページ・コードフェンス・メタ情報に、と役割を分けるのが筋が良さそうという見立てです。

最後に Claude Design が出力した HTML を `yukyu-blog.html` として受け取って、ここで Claude Design 側のセッションは一区切り。

---

## Chapter 3 — Claude Code に引き継いで Nextra 4 に実装

ここからは実装フェーズで、Claude Code に Anthropic API キーを使わせて任せました。

選んだ技術スタック：

- **Next.js 15.5.15**（Next 16 + Nextra 4 で Turbopack の MDX loader が timeout する既知問題を踏んだので 15 に固定）
- **Nextra 4.6.1** + `nextra-theme-blog`
- **Zod 4** で frontmatter スキーマ
- **Vitest** で TDD
- **next-view-transitions** でクライアント遷移
- スタイルは **`globals.css` 1 枚**（Tailwind を使わない選択）

`yukyu-blog.html` から以下を写経していきました。

- `/index` の巨大スラッシュ + 記事番号 (Bの索引感)
- 記事詳細ページの mono / 細い罫線 / TOC（C のドキュメント美学）
- パレット: `#fafaf7` / `#0a0a0a` / `#002ced` / `#ff5a1f`
- フォント: JetBrains Mono / Inter Tight

ルーティングは App Router で素直に：

- `/` トップ（whoami + recent works + index）
- `/page/[n]` ページネーション
- `/posts/[slug]` 記事詳細
- `/tags`, `/tags/[tag]`, `/tags/all` タグ系
- `/rss.xml` RSS（route handler）

---

## Chapter 4 — 236 記事の Markdown を MDX に運ぶ

旧 v2 の記事は `public/source/{slug}/index.md` に 236 件分溜まっていました。これを Nextra の `content/posts/{slug}.mdx` に移すコンバータを TDD で書きました。

地味にハマったところ：

- frontmatter の日付フィールドが `created_at` / `createdAt` / `date` の 3 揺れ → Zod の `LegacyFrontmatterSchema` で `.refine()` 経由で正規化
- JST の日付が UTC に丸まると 1 日ズレる → `formatLocalDate` を `getUTCFullYear` ベースに固定
- MDX の strict JSX パーサが `<br>` を許さない → `selfCloseVoidTags` で `<br />` に
- `class=` が JSX で通らない → `jsxifyHtmlAttributes` で `className=` に
- インライン `style="..."` 文字列も JSX には通らない → `stripInlineStyles` で剥がす
- ↑これらを一括適用するとコードフェンス内の HTML サンプルまで書き換わってしまう → `preservingFencedCode` でフェンスを退避してから変換、戻す
- 退避用 sentinel に NUL バイトを使ったらファイルが git に **binary 扱い** されて diff が読めなくなった → `__FENCE_<n>_5e4f3c__` のような ASCII の長い一意文字列に切り替え

画像も同様に手強く、Vercel の webpack module resolver が URL エンコードされた日本語ファイル名を decode してファイルを探しに行くため、`yukyuメディアポスト.jpeg` 系のファイルがすべて `Module not found` で落ちました。`scripts/normalize-image-paths.ts` で `<ascii>-<sha1>.<ext>` に正規化し、衝突時は内容比較で安全に dedupe するようにしました。

---

## Chapter 5 — レビューを取り込みながら完成させる

PR は Claude のレビューボットを回しながら 4 ラウンドぐらい往復しました。指摘の中で効いたのは：

- `gray-matter` を `devDependencies` に置いていたが SSG 時に呼ばれるため `dependencies` へ
- `loadAll()` の Zod パース失敗を try/catch で **どのファイルが原因か** を含めたエラーに包む
- index 一覧の `<h2>` を `<Link>` の中に入れていたが、`<span>` に降ろして見出し構造の混乱を回避
- `rewriteRelativeImages` が Markdown 画像しか書き換えていなかったので、HTML `<img>` にも、しかも **`preservingFencedCode` の内側で** 適用するように
- `package.json` に `typecheck: "tsc --noEmit"` を追加して、ビルド前に型エラーを catch
- `posts.ts` の単体テストを追加（sort 順 / `getProfileExcerpt` の有無 / `getPostsByTags` の dedupe など 9 件）

ロゴや `cc-by-nc-sa` といった装飾は最後の段階で削ぎ落として、ヘッダは `yukyu.net` のテキスト 1 つだけ、フッタも最低限にしました。トップの whoami セクションには `/posts/me` の最初 2 行を抜粋して表示し、SNS リンクはタグチップ風の小さな box に。recent works はモバイルで 2 列、極小画面で 1 列の 3 段階レスポンシブです。

---

## おわりに

Claude Design で **方向性とレイアウトの骨子** を、Claude Code で **コード化と移行と詰め** を、それぞれ得意な領域に振った構成でした。途中で v2 を root から削除して v3 を昇格させる破壊的な操作も挟みましたが、PR 単位で Vercel preview と CI レビューが回るので、踏み外しても踏みとどまれた感覚があります。

最終的に出来上がった v3 は、白背景 / 細い罫線 / 索引としてのインデックス / mono の詳細ページ、というシンプルな個人ブログに収まりました。fly-by 由来の `#002CED` はリンク色とアクセントだけに残っています。

Source: <https://github.com/yukyu30/yukyu-net>
