前編では Claude Design と Claude Code を発散と収束で分担する流れを紹介しました。後編は、プロトタイプを「毎日使える本番」に変えるための作り込みに踏み込みます。題材は、私が個人開発で、Dolice Labs の運用の傍らで実際に組んだ、データを一枚で見渡すダッシュボードのような静的サイトを想定します。
ここで扱うのは、AI が出した生成物をどこまで土台にしてよいか、ロジックをどう分離するか、データの真実をどこに置くか、そして CI で何を自動化するか、という4点です。どれもプロトタイプを公開物に変える段で必ず立ち止まる判断でした。
生成物のランタイムを作り直さず土台にする
Claude Design が出力するプロトタイプには、ビルド済みのランタイム(生成された support.js のような1枚のJS)が同梱されていることがあります。普通なら「プロトタイプはプロトタイプ、本番は作り直す」と考えるところですが、私はあえてランタイムごと引き継ぐ判断をしました。
判断の軸は単純で、その生成物が自分の要件と噛み合うかどうかです。今回は次の条件が揃っていました。
依存ゼロ・ビルドレスで、<script src> で読むだけ。バンドラもインストールも要らない
すでにプロトタイプがそのまま動いている。フレームワークへ移植して得るものが薄い
ランタイムが1枚のJSに閉じているので、最悪は中を読めば全部そこにある
「AI が生成したから本番では使わない」と反射的に避けるのではなく、性質が要件に合うかで決める。長く使う個人開発の道具では、依存を抱えないこと自体が安心材料になりました。逆に、この条件が噛み合わなければ載せ替えていたと思います。生成物は編集対象にせず、ルールに「生成物・編集しない」と明記しておくのが安全です。
ロジックを mixin で分離する
プロトタイプは1枚のHTMLに全部入りになりがちです。これだと変更箇所が区分しづらく、メンテが重くなります。そこで実装の大半を外部の js/*.js に出し、グローバルなメソッド集に登録しておいて、本体の末尾で合成する形にしました。
// js/format.js などの末尾(何度読んでも安全な冪等パターンで登録)
window.AppLogic = Object. assign (window.AppLogic || {}, {
yen ( n ) { return '¥' + Math. round (n). toLocaleString ( 'en-US' ); },
pct ( n ) { return (n * 100 ). toFixed ( 1 ) + '%' ; },
});
// 本体側の末尾で合成する
Object. assign ( Component . prototype , window.AppLogic);
ここで意識したのは、ランタイムが名前で呼ぶ契約面(コンストラクタやライフサイクル、描画用のメソッド)だけをインラインに残し、それ以外は外部ファイルへ逃がすという線引きです。「画面をどう記述するか」はランタイムに従い、「コードと運用をどう構成するか」は自分で決める。この境界をはっきりさせると、本番化フェーズで何度細部をいじっても見通しが保てます。
データの真実を1か所に閉じる
可視化系で一番事故りやすいのが、表示用と集計用でデータが二重管理になり、表示が嘘をつくことです。これは設計で潰せます。私が採ったのは、人が追記する元データ(取引台帳のようなCSV)を唯一の正とし、アプリが読むデータはそこから生成する派生物にする、という形です。
transactions.csv ─┐
├─ import.mjs ─→ holdings.json(アプリが読む派生物)
prices.csv ───────┘
↑ update-prices.mjs(自動取得)
派生物は直接編集を禁止し、元データとの一致を pre-commit フックで検査します。手で更新が必要になるのは、基本的に元データへの追記だけ。表示が事実とずれない構造を先に作っておくと、後から機能を足しても破綻しません。ブラウザ側は一切リポジトリに書き込まず、ライブ取得した値は失敗時のフォールバックにのみ使う、と決めておくと、サーバもDBも持たずに動的な見え方を保てます。
CI で「壊れる前提」の自動更新を組む
外部から値を取ってくる部分は、非公式APIの直叩きになることもあり、いつ壊れても困らない備えが要ります。私は取得を CI 側に隔離し、ブラウザからは叩かない構成にしました。日次の自動実行で、値の取得・派生物の再生成・スナップショット追記・共有画像の再生成・デプロイまでを一本のワークフローで回します。
# .github/workflows/snapshot.yml(要点のみ)
on :
schedule :
- cron : "0 13 * * *" # 毎日 22:00 JST
permissions :
contents : write
jobs :
update :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@<commit-sha> # SHA でピン留め
- run : node scripts/update-prices.mjs # 失敗時は既存値を据え置き
- run : node scripts/snapshot.mjs # 差分があるときだけコミット
ここで大事なのは、取得に失敗したら既存値を据え置く、という安全側の設計です。壊れても古い値のままで済み、画面が空になりません。外部Actionは commit SHA で固定しておくと、Action 乗っ取りのようなサプライチェーン経路の事故も避けられます。自動化は「うまくいく前提」ではなく「壊れたときに被害を出さない前提」で組むのが、本番運用では効きました。
OGP 画像は実ブラウザで撮って寸分違わず揃える
意外と粘ることになるのが、SNS でシェアしたときの見え方です。クローラは JS を実行しないため、共有画像は静的にコミットされた PNG である必要があり、クライアントでの動的生成は使えません。そこで、画像用の独立ページを用意し、CI 上で実ブラウザに開かせてその領域を撮影する形にしました。
// scripts/og.mjs(要点)
import { chromium } from 'playwright' ;
const browser = await chromium. launch ();
const page = await browser. newPage ({ viewport: { width: 1200 , height: 630 } });
await page. goto ( 'file://' + process. cwd () + '/og.html' );
await page. evaluate (() => document.fonts.ready); // フォント確定を待つ
await page. locator ( '#card' ). screenshot ({ path: 'og.png' });
await browser. close ();
Canvas で描き直す手もありますが、字形やレイアウトがサイト本体と乖離するのが嫌で、実ブラウザ撮影を選びました。document.fonts.ready を待ってから撮ることで、本体と同じ字形に揃います。実際にシェア検証ツールでプレビューして初めて、タイトルや説明文の不足に気づくこともあり、この「実物で確かめる」工程は省けませんでした。
本番化でつまずいた3つの落とし穴
プロトタイプを公開物に変える過程で、私が実際にハマった注意点を3つに分けて残しておきます。
生成物を編集してしまう罠
最初の落とし穴は、便利だからとつい生成物のランタイムに手を入れてしまうことです。直接いじっても次の再生成で上書きされるため、変更が消えて原因不明の不具合に見えます。対処は単純で、ルールに「生成物・編集しない」と明記し、pre-commit で編集を検知して弾くのをお勧めします。私はこの一手で同じ事故を二度と起こさなくなりました。
グラフの点が楕円に潰れる罠
二つ目は描画の細部です。SVG を横幅いっぱいに引き伸ばすと、丸い点まで楕円に潰れてしまいます。回避策として、点だけは SVG をやめ、割合配置の真円要素で重ねて描くと、横長でも円が円のまま保てます。実機で見て初めて気づく類の崩れなので、本番運用に入る前に必ず実画面で確認することを推奨します。
キャッシュで古い画面が固定される罠
三つ目は配信側です。エッジキャッシュを挟むと、更新したつもりの画面が古いまま読者に配信され続けることがあります。私の対処は、デプロイのたびにバージョン定数を上げて既存キャッシュを失効させ、匿名状態で実際の配信内容を確認することです。「サーバーは直っているのに直らない」という切り分けで時間を溶かさないために、この確認は外せません。
仕上げに効いた小さな規約
最後に、往復を安定させる地味な工夫を一つ。プロジェクトの前提を CLAUDE.md に、ドメイン固有のルールを .claude/rules/ に分けて書いておくと、毎回の会話で説明し直さずに作業へ入れます。
# プロジェクトの土台
- 見た目 → styles.css
- ロジック → js/
- 生成物 support.js は編集しない(再生成で上書きされる)
- デザイン実値を変えたら rules のデザイン方針も同期する
こうした規約を pre-commit フックで機械的に検査するようにしておくと、やってはいけないことを人の注意力ではなく仕組みの側で止められます。AI に作業を任せても規約に沿ってくれるので、ドキュメントと実装の乖離が起きにくくなりました。本番化とは、派手な機能を足すことよりも、こうした土台を静かに整える作業の積み重ねなのだと、私は感じています。