ブログの「着せ替え」をAgentと30分で実装した — Light / Warm / Night 3テーマ対応

記事
デザイン・イラスト
管理画面でボタンを1つ押したら、サイト全体の見た目がガラッと変わった。
「着せ替え」と呼んでいるこの機能を、Agent と一緒に30分で作った話を書く。

2026-02-22-theme-before.png

 BEFORE — 色がハードコードされた状態


もともとの my-blog は Warm テーマ1種類だけだった。背景の `#f6f4ee` やテキストの `#1a1a1a` がコード中に直接書かれていて、「ダークモードにしたいな」と思っても簡単には変えられない。



2026-02-22-theme-before.png

![変更前のトップページ(Warmテーマ)](/figures/2026-02-22-theme-before.png)

温かみのあるベージュ系の配色。これはこれで気に入っていたが、夜に見ると少し眩しい。

2026-02-22-theme-after-night.png

 AFTER — Night テーマに切り替えた瞬間

管理画面でテーマを Night に切り替えると、同じページがこうなる。

![Nightテーマに切り替えたトップページ](/figures/2026-02-22-theme-after-night.png)
背景は `#1a1b1e`、テキストは `#e4e5e7`。アクセントカラーもシアン系に自動で切り替わる。夜の閲覧が格段に楽になった。

2026-02-22-theme-settings.png

 管理画面 — ワンクリックで切替

テーマの切り替えは `/admin/theme` から行う。Light / Warm / Night の3カードが並んでいて、押すだけで即反映。
![テーマ設定画面](/figures/2026-02-22-theme-settings.png)

各カードにはカラーパレットのプレビューが表示されている。「Warm(デフォルト)(現在)」のように、今どのテーマが適用されているかも一目でわかる。次回ページ読み込み時に全訪問者に反映される仕組みだ。
ちなみに Admin ページ自体にも変化があった。テーマ機能を実装したことで「テーマ設定」ボタンが追加された。

 Agent との協働プロセス

実装は以下の6ステップで進めた。
1. **Supabase テーブル設計** — `site_settings` テーブルを作成。`key = 'theme'` で `light / warm / night` の値を管理する

2. **CSS変数定義** — 3テーマ × 8色を `globals.css` に定義。`:root` は Warm をデフォルトにした

3. **FOUC防止** — `<head>` 内の inline script で `localStorage` からテーマを即座に適用。ページ読み込み時のちらつきを防ぐ

4. **ThemeSync コンポーネント** — Supabase から最新テーマを取得し、`localStorage` と `data-theme` 属性を更新する

5. **管理画面UI** — 3つのカード形式で、クリック → `site_settings` テーブルに upsert → 即反映

6. **15ファイルの色移行** — ハードコードされた Tailwind 色 (`text-gray-600`, `bg-white` など) を CSS変数 (`var(--muted)`, `var(--surface)`) に置き換え

Agent には「Warm テーマをデフォルトにして、Light と Night を追加したい。管理画面から切り替えられるようにして」と伝えた。テーブル設計から CSS 定義、FOUC 対策まで一気に提案してくれた。
Codex レビューでは blocking 指摘が5件出た。RLS の設定漏れ、import パスの不一致、FOUC 対策の不備など。全件修正して再レビューで pass した。
## 困った具体例
| # | 状況 | 困りごと | 解消 |
|---|------|---------|------|
| 1 | FOUC(ちらつき) | テーマ適用前に一瞬白背景が見える | `<head>` 内の inline script + `localStorage` キャッシュで防止 |
| 2 | RLS 設定漏れ | 全ユーザーがテーマを変更できてしまう | `auth.uid()` で管理者 UUID に限定 |
| 3 | ハードコード色の見落とし | Night テーマで一部のテキストが見えない | 15ファイルを総点検して CSS変数に統一 |

特に3番目が地味に大変だった。Night テーマに切り替えたら「あれ、ここのテキストが見えない」というのが次々出てくる。`text-gray-600` のように Tailwind で直接指定していた箇所が、黒背景に対してコントラスト不足になっていた。Agent と一緒に15ファイルを洗い出して、すべて `var(--muted)` や `var(--ink)` に置き換えた。

 結果

- **実装時間**: Agent との協働で約30分
- **変更ファイル数**: 15ファイル以上
- **テーマ数**: 3(Light / Warm / Night)、追加も容易
- **FOUC**: inline script + `localStorage` で抑制済み
CSS変数の設計がベースにあったから、テーマの追加は `globals.css` に変数セットを1つ足すだけで済む。将来4番目のテーマを作りたくなっても、数分で対応できる。

 次の1歩

- ユーザーごとのテーマ選択(訪問者が自分の好みで切り替えられる機能)
- テーマのカスタムカラー対応
- 切り替え時のトランジションアニメーション
まずは管理者が全体のトーンを決める仕組みができた。ここから先は「訪問者自身が選べる」方向に進化させていきたい
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す ココナラコンテンツマーケット ノウハウ記事・テンプレート・デザイン素材はこちら