バイブコーディングでライフプランサービスを作った!
個人開発として、忙しい私生活のスキマ時間で“バイブコーディング”しながらライフプランシミュレーターをゼロから公開まで作った過程を、コミットの流れとともに振り返ります。
「いま乗ってる波に任せる」──そんな感覚で小さく進める“バイブコーディング”のやり方で、ライフプランサービスを個人開発しました。私生活がかなり忙しく、まとまった時間が取れない期間だったのですが、毎回30〜60分の短いセッションでも確実に前進できるよう、AIに指示を切り出してはコミットを重ねるスタイルで進めました。本記事では、どんな指示をAIに出したか、どこでつまずいてどう解決したかを要点でまとめます。
つくったものと目的
- 家計の収支・資産推移を年単位で予測するライフプランシミュレーター
- 夫婦・子ども・教育費・イベントなどを入力し、資産推移と収入のグラフ、年ごとの内訳テーブルを表示
- React + Vite フロントエンド、Cloudflare Pagesにデプロイ、E2E/Unitテストで品質確保
個人開発者としてずっと作ってみたかったジャンルでした。将来設計を「ざっくりでも形にしてみる」ことが目的で、まずは自分が使える最低限のUXと計算の透明性を重視しました。
バイブコーディングの進め方
- ルールは「短時間で完結するタスクに分解」「毎回ひとつの成果をコミット」。
- AIには具体的な入出力・制約・完了条件を明示して、PR粒度の変更を繰り返す。
- ガードレールとして Vitest と Playwright を早めに導入し、壊れてもすぐ気づける状態に。
忙しい私生活の合間でも、ノッているときに一気に進め、波が引いたら止める。このメリハリが“バイブ”の正体です。
開発ハイライト(要約)
- 入力とデータ管理: 経済設定・家計・ライフイベント・子ども教育費を段階的に整備。Zod + React Hook Form で型安全にし、useLifePlanLocalStorage で永続化とバリデーションを統合。
- 表示と分析: 資産/収入チャート(退職基準線付き)と、年ごとの内訳テーブル(年間貯蓄・教育マイルストーン)で「結果の見え方」と「計算の透明性」を両立。
- UX 改善: タブ構成から単一ロングページ + フローティングナビへ。年/月セレクト(日本語)やオートクローズで操作ステップを削減。スクロールの安定化やセクションIDの整理で移動体験を改善。
- 品質保証: Vitest(ユニット)/ Playwright(E2E)を導入し、CI でフルフローを検証。ブラウザキャッシュの最適化でパイプラインを効率化。
- 収益化の実験: AdSense を用いた Ad-gated Prediction を実装。二重初期化防止、sessionStorage の初期化と状態管理で運用の罠を回避。
- 計測と運用: GA4 / Microsoft Clarity を Partytown 経由で導入。Cloudflare Pages のルート設定とワーカー設定(observability など)を調整。
- 仕上げの整備: GlobalFooter、Terms/Privacy/NotFound の整備、BuyMeACoffee のサポート導線を追加。
実際にAIに出した主な指示(抜粋)
“バイブ”で乗れているときは、AIに対して次のような指示を小刻みに出しました。要約すると「入出力の契約を切り出し、完了条件を明示する」です。
- Zodスキーマで型安全にしつつ、localStorage と同期する useLifePlanLocalStorage を実装して。シリアライズ/デシリアライズとマイグレーションも考慮。
- 予測ロジック用の hooks を分割し、グラフ(資産/収入)とテーブル(年ごとの内訳)を再利用しやすい形で組み直して。
- E2E のフルフローを書いて。Home→入力→予測→グラフ/テーブル表示までを1本で検証。PlaywrightのテストIDsとセクションナビに寄せる。
- GA4 と Microsoft Clarity を最小構成で導入。Partytown 経由にして、実測でパフォーマンス影響を抑える。
- タブUIを単一ロングページにリファクタし、右下固定のフローティングナビでセクション間を移動できるように。
- Ad-Gated Prediction を入れて。広告の視認(状態変化)をトリガに結果を解放。二重初期化やセッション引き継ぎの罠を避ける実装にして。
- アクセシビリティ(ラベル/フォーカス/セマンティクス)と国際化前提の日本語月セレクトを導入。
- Cloudflare Pages へのデプロイ設定(wrangler, routes, observabilityの調整)とCIに E2E を組み込み。
例えば、広告の実装は次のような“契約”で指示しました(イメージ)。
// 契約: 広告が1度でも視認状態になったら、予測結果を解放する
// - ページロード時に sessionStorage を初期化
// - 二重初期化を避ける(<ins data-ad-status> を参照)
// - 解除状態はセッション内でのみ維持
useEffect(() => {
sessionStorage.removeItem("lp:ad-unlocked")
}, [])
const [unlocked, setUnlocked] = useState(false)
const onAdStatus = (status: string) => {
if (status === "filled") {
sessionStorage.setItem("lp:ad-unlocked", "1")
setUnlocked(true)
}
}
return unlocked ? <PredictionResult /> : (
<AdGate onStatusChange={onAdStatus} />
)
技術スタックと設計メモ
- フロントエンド: React 19 + Vite(Life Plan フロントエンド)
- フォーム: React Hook Form + Zod
- 可視化: Recharts(資産/収入チャート)
- ストレージ: localStorage フックで永続化(スキーマバリデーション付き)
- テスト: Vitest(ユニット)+ Playwright(E2E)
- 分析: GA4 + Microsoft Clarity(Partytown 経由)
- インフラ: Cloudflare Pages(wrangler でルート設定)
設計上は「フォーム/ロジック/表示」を薄く分離して、ユースケースを hooks に寄せる方針に。後追いでの仕様変更(ロングページ化、広告ゲート化)に耐えられるようにしました。
個人開発 × 忙しい私生活での工夫
まとまった時間が取れない中でも、「小さく決めて、小さく進める」を徹底しました。バイブコーディングは“勢いがあるときに最大化する”のに向いていて、停滞しそうな日は「テスト1本だけ書く」「ラベルを直す」など、進捗ゼロを避けるメニューを用意。AIへの指示もテンプレ化して、認知コストを下げました。
また、人と同期的に進めるやり方では自分の実動時間と同じ時間しかAIを使うことができません。しかし、Issue を作っておき、それに Copilot をアサインしておくことで、0→1 をやってくれて、運が良ければそのままマージできます。これにより AI と非同期的にタスクを実行でき、子育てをしている少ない時間の中でも効率的に開発を進められました。
これから
- 複数シナリオ比較(ベース/強気/弱気)
- 投資アセット配分とリバランスの入力
- 退職金/年金の詳細パラメータ
- プリセットの保存/読み込み、CSVエクスポート
プロダクトとしては「透明性のある計算」と「入力のしやすさ」を引き続き磨いていきます。
まとめ
忙しい時期こそ、バイブコーディングで“波に乗った分だけ前に進める”のが個人開発には相性が良かったです。コミットに正直な開発フローを残しておくと、振り返りもしやすく、次の波に乗る助走にもなりました。引き続き、実用と学びの両輪で育てていきます。