--- title: "アマチュアが AI 駆動 + フルスタック 1 人で Floatia ロードマップを完走させた話" description: "アマチュア (独学数年) のプログラマが、Claude (Opus 4.7) を使った AI 駆動 + フルスタック 1 人体制で「Floatia (旧 Drift)」 — 280字の手紙を瓶に詰めて流す一期一会の匿名 SNS — を作っている話。git 開始から 10 日で β 公開水準。世界観の哲学、技術選定 (Go + chi + pgx、ORM なし、最新 framework 採用、セルフホスト + CF Tunnel)、ロードマップ 4 軸 (削除廃止 / 抽選最適化 / 経年表現 / 整合性) を 2026-04-26 にまとめて完走させた経緯、AI 駆動の盲点と CLAUDE.md 性能規約まで掘り下げる。" url: https://ryuuneko.com/blog/floatia-roadmap-completed published: 2026-05-03 04:18:37.659482 updated: 2026-06-16 09:16:43.899016 --- 最初に立場を明らかにしておくと、私は **アマチュア (独学で数年) のプログラマ** で、職業エンジニアではない。普段はぜんぜん別の仕事をしていて、コードを書くのは完全に趣味。アマチュア無線家やアマチュアスポーツ選手と同じ温度感、と思ってもらえれば。 そのアマチュアが、Floatia (旧 Drift。匿名で瓶を海に流すコミュニケーション体験) を **ほぼ全部 Claude (Opus 4.7) を使った AI 駆動開発で書いている**。仕様の議論・設計・実装・テスト・レビューまで、人間 (= 私) は方向決めとレビュー観点の提示が中心で、コード自体は AI が書く。 しかも **フルスタック 1 人体制**: Frontend (Next.js + React) / Backend (Go) / DB (Postgres) / Infra (Docker Compose + Cloudflare Tunnel + セルフホスト) / 認証 / 観測 / 監査 / 世界観コピー / アニメーション まで全レイヤを 1 人 + AI で書いている。チームメンバーはいない、デザイナーもいない、SRE もいない。**AI 駆動だからこそ、アマチュア 1 人でこれを全部回せている**。 **2026-05 時点で β 公開中** → :::callout{type="info" title="この記事の要約"} - アマチュアが AI 駆動 + フルスタック 1 人で β SNS をローンチした - git 開始から **10 日** で β 公開水準 - backend ロードマップ 4 軸 (削除廃止 / 抽選最適化 / 経年表現 / 整合性) を 2026-04-26 に完走 - 一番の学び: **AI に書かせる前提で `CLAUDE.md` を整備するのが最大の投資先** ::: ## Floatia とは — 「誰かの海へ、手紙を」 **Floatia は「280字の手紙を瓶に詰めて海に流す、一期一会の匿名 SNS」**。 - 流すと瓶は海を漂う - 別の誰かが海辺を歩いていて、たまたま拾う - 封を開けて読む。書き足して再び流すこともできる - そして二度と同じ瓶には会えない (= 一期一会) それだけ。リプライツリーも、フォローも、いいねも、通知もない。 ### 一期一会を仕様に落とす 「一期一会」を世界観コピーで語るだけでなく、**仕様レベルで強制している**: - **通知なし** — 「あなたの瓶に返信が」「新着があります」を一切作らない - **新着バッジなし** — 戻ってきても何が増えたかわからない - **活動フィードなし** — 自分の足跡をたどる動線を持たない - **続きを追えない設計** — 自分が拾ったあとに別の人が書き足すと、その瓶はもう自分には読めない。「あのとき読んだ続き」を追うことはできない 「現代の SNS が当然のように持っている機能」を **意図的に持たない**。これは制約ではなく、**それこそが体験の核**。 ## 開発スケジュール — ざっくりアジャイル git history で追える範囲のマイルストーン: | 日付 | やったこと | |---|---| | 2026-04-23 | `Drift v0.1 — initial prototype` 公開 git 開始。同日に **SQLite → Postgres 16 移行** | | 2026-04-24 | **Node/TS → Go 全書き換え** + cut-over + 安定化。Next.js 14 → 16 bump、admin / feedback / announcements を一気に積む | | 2026-04-26 | **4 軸ロードマップ A/B/C/D 完走** | | 2026-04-27 | 5 段ワークフロー (プラン → red テスト → 実装 → green テスト → レビュー) を恒常化 | | 2026-04-30 | **drift → Floatia リネーム**、dual-host 開始 | git 開始から **10 日** で β 公開水準。git 開始前にローカルで数日の試作期間があったので、実際の総開発期間は **2 週間ちょっと** (試作の詳細は後述「移行履歴」)。 「アジャイル」と書いたが、実際の運用は: - **5 段ワークフロー** をタスク単位で踏む。durable に固定 - sprint は無い。「今日はここまで」を毎晩決める - 機能の優先度は「世界観に効くか / scale に効くか / セキュリティに効くか」の 3 軸で都度判定 - AI に **「規模 S / M / L」** で見積もりを出させて、L だと当日中に着手しない AI 駆動の利点は **「実装の見積もりが正確になる」** こと。AI が「規模 S なら 30 分、L なら半日」と出してくれて、それが結構当たる。人間の見積もりは楽観バイアスが乗るが、AI は淡々と「これは N 箇所触るから L」と判断するので、スケジュールが意外とブレない。 もう一つ大きいのは **「レイヤ間の context switch コストが激減する」** こと。普通フルスタック 1 人でやると「Go の `pgx` 構文 → Next.js の Server Component → Docker Compose の env_file」で 1 日中ヘッドが切り替わって疲弊する。AI 駆動だと AI 側が各レイヤの細部を保持してくれるので、人間は **「世界観としてどうあるべきか / scale としてどうあるべきか」** という抽象度の高い判断だけに集中できる。 ## 技術選定 — 「趣味だからできた」自由度 **最初に断っておくと、この技術選定は「趣味で作っているからこそできた」**。仕事のプロダクトだったら絶対に通らない判断 (出てすぐの最新 framework / library を採用 / ORM を入れない / セルフホスト / 軽量にインフラ集約) が並んでいる。「AI に書かせやすい」「自分が試したい」「手数を減らせる」を最大化していて、**保守性や引き継ぎやすさは捨てている**。 ### スタック | レイヤ | 採用 | |---|---| | Backend | Go + `chi` + `pgx`、単一バイナリ ~40MB、起動 ~100ms | | DB | PostgreSQL | | Frontend | Next.js + React + Tailwind + Framer Motion + `next-intl` | | 認証 | Argon2id + JWT HS256 + HttpOnly Cookie (WebAuthn は将来用にスキーマのみ用意・未実装) | | テスト | DB 統合テスト + E2E (主要パスのみ) | | 観測 | クエリ統計 + プロファイラ + slow-query 追跡 + 自前アラート | | ホスティング | セルフホスト + Cloudflare Zero Trust トンネル (ports 公開ゼロ) | ### 移行履歴 — 4 段、ほぼ全部 git 開始前 1. **Cloudflare Workers + D1** (試作 day 1) — D1 が必要な extension を持たず詰んだ 2. **Node 20 + Hono + better-sqlite3** (試作 day 2-3) — multi-writer に弱い 3. **Node 20 + Hono + Postgres 16** (2026-04-23) — git 開始日 4. **Go + chi + pgx** (2026-04-24) ← 現行。**前日からたった 1 日で書き換え + cut-over**、スループットとメモリが目に見えて改善 3 → 4 の移行は、Argon2id PHC 形式 + JWT HS256 で認証スキームを互換にしておき (新ランタイムが旧ハッシュも検証可能)、**ほぼ無停止で runtime を切り替えられた**。「runtime を 1 日で全書き換えする」のは AI 駆動ならではの動き。 ### なぜ Go + chi + pgx か - **静的型 + シンプルな構文** → AI が型で間違いを構造的に減らせる。Rust も候補だったがライフタイムとマクロが AI の生成ばらつきを増やす方向に効くので除外 - **chi は薄い** — middleware を積む思想で、generated code が独自 magic に依存しない - **pgx は超薄い** — ORM は使わない。**hot path で SQL を制御したい**用途に直接マッチ ### なぜ ORM を使わないか - **AI は ORM の DSL より素の SQL のほうが圧倒的に上手い** - **クエリの計算量が透明** — `EXPLAIN ANALYZE` で見たコストとコードが 1:1 - **migration は冪等 SQL でやる** — `schema.sql` を起動時に流すだけ 仕事のプロダクトだったら ORM は入れる。**1 人で書いてレビュアーも自分なら、その肩代わりが要らない**。 ## ロードマップ完走 — C → B → A → D UI/UX フェーズが落ち着いたタイミングで仕込んでいた 4 軸を 2026-04-26 にまとめて完走させた。 - **A. 世界観**: 削除廃止 + 深海復活 + 経年表現 - **B. 性能**: 抽選アルゴリズム + count 集約 - **C. メタ**: `CLAUDE.md` 性能規約 - **D. 整合性**: hash chain + content_hash 漸進化 着手順は **C → B → A → D**。メタ規約 → 性能基盤 → 世界観の上物 → 整合性の中長期路線、という積み方。 ### C. メタ — `CLAUDE.md` に性能規約を刻む 最初にやったのは規約整備。AI 駆動である以上、AI に渡る `CLAUDE.md` が **そのままコード品質の上限** になる。コードレビューで都度直すより、規約を直したほうが伝播が早い。 - 「やってはいけない」セクションに、**hot path での** `COUNT(*)` 多発 / N+1 / `ORDER BY RANDOM()` / unbounded SELECT を禁止 の 4 条を追加 - 新節 **「性能 posture (hot / warm / cold path)」** を作成。endpoint ごとに温度感を表で定義 - テスト規約に **query count assertion** を追加 ### B. 性能 — 抽選アルゴリズム + count 集約 - pick 抽選: `ORDER BY RANDOM()` → rejection sampling アルゴリズムへ。母集団膨張に対して scale-invariant (~1ms 前後を維持) - 多重 `COUNT(*)` を集計用シングルトン表 (トリガ更新) + 短期キャッシュで **O(1)** 化 - N+1 を `IN ($1, $2, ...)` に統合 ### A. 世界観 — 削除廃止 + 深海復活 + 経年表現 - 物理削除のクリーンアップを廃止。古い瓶も別フェーズで残す - pick 抽選で **drifting / deep の tier 分け**。「深い海から、古い瓶が偶然浮上した」体験 - 瓶の表示コンポーネントに経年表現 (海藻 / 貝殻 / 退色) を追加。古い瓶ほど装飾が増える variance を仕込んだ - 「これは古い瓶」と明示せず、視覚と時刻表記でさりげなく古さを匂わす 世界観論: 「流した瓶との別れも完全な別れ」 (= 「拾った瓶との出会いも一度きり」と対称) が一期一会の閉じ方として美しい。 ### D. 整合性 — hash chain + content_hash 漸進化 - 監査チェーンの hash chain は **retention 上限** があるため頭打ち、現状 OK - メッセージの content hash 全件 verify は将来詰まる → cursor-based 漸進バックグラウンド + N% サンプリング四半期 cron に - 監査チェーンの先端を外部に退避する既存路線は維持 ## AI 駆動開発の盲点 — なぜ C を最初にやったのか ここが今回一番書きたかったところ。 「無駄が漏れた構造」(`COUNT(*)` 多発 / N+1 / `ORDER BY RANDOM()`) は、AI が要件を素直に SQL に翻訳する癖から来る。「ランダムに 1 件」と頼めば `ORDER BY RANDOM()`、「件数を 6 つ表示」と頼めば `COUNT(*)` を 6 個並べる。AI は「読みやすい」「短い」「動く」を優先する傾向があるので、これは構造的な特性。 問題は、これが厄介な性質を持っていること: - **バグじゃない** — 動くし、結果も正しい - **レビューで止まらない** — 行数も読みやすさも問題なし - **小規模時には実害がない** — 1000 行の `COUNT(*)` は 1ms で返る - **性能テストが規約に無いと検出できない** — 単体テストはパスする つまり「動く + 読める + 小規模で速い」の三拍子で **構造的に検出できない**。AI レビューに頼っても止まらない (AI 同士は同じ盲点を共有しているので、書き手 AI が「OK」とするコードを、レビュワー AI も「OK」と通してしまう)。 人間レビューでも、「動いて読めるコード」を性能観点で止めるのは判断コストが高い。「これ将来的に詰まりそうなんだよな…でも今は動くし…」で見送りがちで、私自身も初期はそうだった。 C の規約追加で、 1. **「やってはいけないリスト」** — AI 生成時の負の制約として効く 2. **「temperature 表」** — endpoint ごとの温度感を AI に伝える共通語彙 3. **query count assertion** — テストでの自動検出 の **3 段で結界化** した。AI 駆動を続ける以上、こういう「正しいが筋が悪い」構造を **規約側で止める仕組み** が必要だ、というのが今回の一番の学び。 :::callout{type="tip" title="AI 駆動開発で一番大事なこと"} **AI に書かせる前提で `CLAUDE.md` を整備するのが、AI 駆動開発における最大の投資先**。コードレビューで都度直すより格段に効く。 ::: ## ふりかえり AI 駆動開発で 4 軸を 2026-04-26 当日にまとめて完走できたのは、各軸が **小さく独立** していて **規約 (C) で品質保証** されていたから。規模 L の A も、B で hot path が綺麗になっていたので追加変更が局所的に閉じた。 技術選定の話で書いた **「ORM を使わず素の pgx で SQL を直書きする」** 判断が、B 章の hot path 最適化を現実的にしたのも大きい。AI 駆動 + 性能要件 + 世界観の 3 つを同時に満たすには、**抽象を一段薄くする** (= ORM を抜く、framework を薄いものにする、middleware は自分で積む) のが結果的に効いた。これは **趣味だから抜けた** 抽象でもある。仕事のプロダクトだったら ORM は入れていた。 git 開始から 10 日で β 公開水準まで持っていけた事実が、AI 駆動 + 趣味プロジェクト + 規約整備の組み合わせの説得材料として一番強い。 ロードマップ完結 (2026-04-26)。次は phase が止まった頃にまた書く。 --- **β 公開中**: — 「誰かの海へ、手紙を」 --- *※本記事は2026年6月時点の情報をもとにしています。サービス・コマンド・仕様は予告なく変わることがあります。*