はじめに
Claude Code でWebサービスを作る記事は既にたくさんあります。でも、実際に使ってみると「なんか記事と全然違うんだけど...」と感じたことはありませんか?
デザイナー出身でバックエンド経験が浅い私が、リユース事業の在庫管理システムを実働2ヶ月・運用コスト月数百円で本番稼働させました。
ただし、それは「AIに丸投げして完成」ではなく、Claude Codeの癖を理解して、細かく制御しながら進めた結果です。
この記事では、よくある成功談ではなく、実際にハマったポイントと具体的な対処法を中心に書きます。
プロジェクト概要
開発期間
- Initial commit: 2025年5月23日
- 6〜8月: ほとんど稼働せず
- 9月から本格稼働: 実働約2ヶ月
システムの役割
- 在庫のステータス管理(撮影待ち → 入力待ち → チェック待ち → 値付け待ち → 出品中 → 売却済み等)
- ユーザー権限管理(管理者、正社員、パートタイム、フリーランス)
- CSVインポート・エクスポート
- 外部API(ReCORE)との自動同期
- 作業履歴の記録
技術スタック
当初の構成(Flask時代)
- Backend: Flask + PostgreSQL(Docker)
- Frontend: Next.js
- Deploy: 未定
最終的な構成
- Frontend/Backend: Next.js 15 + API Routes
- Database: Supabase(PostgreSQL)
- Auto Sync: AWS Lambda(EventBridge Scheduler で8時間ごと実行)
- Deploy: Vercel
- 外部API: ReCORE API
技術スタック変更の経緯
最初に技術スタックを固めておいた方が開発はスムーズですが、作っていく上でより良い構成が見えてくるのはよくある話です。
今回は Flask + Docker PostgreSQL → Next.js API Routes + Supabase + Lambda に移行しました。
移行の理由
-
Vercelデプロイの容易性: Next.jsだけなら
git push
で自動デプロイ - インフラの簡素化: Dockerホスティング不要、Supabaseがデータベースを管理
- コスト削減: 社内サービスなのでSupabaseも Vercelも無料枠で十分動作
- タイムアウト対策: 長時間処理(ReCORE API同期)はLambdaに分離
この辺りの知見が得られたのも大きな収穫でした。
開発で苦労したポイント
1. ポート番号の管理
問題点:
Claude Codeはエラーが出るたびに新しいポート番号でサーバーを起動しようとします。気づけば:3000
, :3001
, :3002
...と無限に増殖し、並行して開発している別プロジェクトのローカルサーバーまで止めてくることがありました。
解決策:
# CLAUDE.md に明記
- 他と競合するから3005ポートを毎回使用してください。
- 不調時には新しく立ち上げるのではなく一度その3005番を止めて再起動させてください
具体的なポート番号を指定し、「新規起動ではなく再起動」を徹底させました。
2. Supabaseのページネーション制限
問題点:
Supabaseはページング無しだと上限1000件しか取得できません。1001件目以降の処理が漏れることが頻発しました。
解決策:
// 全件取得する場合はページネーションを実装
const pageSize = 1000;
let page = 0;
let allItems = [];
let hasMore = true;
while (hasMore) {
const { data, error } = await supabase
.from('items')
.select('*')
.range(page * pageSize, (page + 1) * pageSize - 1);
if (data && data.length > 0) {
allItems = allItems.concat(data);
page++;
} else {
hasMore = false;
}
}
CLAUDE.mdに具体的なコード例を記載しておくと確実です。
3. デプロイとSQL実行の制御
問題点:
CLAUDE.mdに「勝手にデプロイするな」とだけ書いても、Claude Codeは良かれと思ってデプロイしてしまいます。
解決策:
.claude/settings.local.json
で特定のツールに対してユーザー承認を必須化しました。
{
"mcpServers": {},
"ask": [
"Bash(git commit*)",
"Bash(git push*)",
"Bash(vercel*)",
"Bash(aws*)",
"Bash(psql*)"
]
}
"ask"
に指定したコマンドパターンは、実行前に必ずユーザーの承認を求めるようになります。これで意図しないデプロイやSQL実行を防げます。
4. テストの粒度を明確に指定
問題点:
「テストして完了してから教えてください」と伝えると、良くても結合テストまでしかやってくれません。「完了しました!」と報告されてページを開いた瞬間にエラーが出ることも頻発。
解決策(気休め):
# CLAUDE.md に明記
- Localhostで実際のUIを試したE2Eテストを行え
- APIやDBだけのテストで完了報告するな
- ログインが必要ならReadme.mdにadminのIDパスワードが書いてある
- Puppeteerを使ってE2Eテストをしろ
- 「〜します」とだけ言ってやらないの意味がわからない
また、Puppeteerのテストコードを格納する場所を決めておかないと、ディレクトリルートが無限に汚染されます。さらに、明示的に指示しないと既存のテストコードも参照してくれないため、毎回認証でコケていました。
ただし正直なところ: CLAUDE.mdに記載した内容も守ってくれないので、気休めにしかなりません。ここはもうちょっと方法を考えるなり、Claude Code側でのアップデートを待つなりする必要があります。
5. サードパーティAPIの異常系ハンドリング
問題点:
「APIを叩いて、結果が存在しなければそのidのステータスは処理完了としてください」と伝えたら、認証ミス等の異常系でレスポンスが無い場合も「処理完了」としてしまいました。
解決策:
異常系の扱いを明示的に指示します。
# CLAUDE.md に明記
#### HTTPステータスコードの意味
- 200 OK: 成功、データ取得成功
- 400 Bad Request: 存在しないITコードを含むと400エラー
- 422 Unprocessable Entity: Content-Typeヘッダーが原因
- 404 Not Found: エンドポイント自体が存在しない
- ネットワークエラー: 接続失敗、タイムアウト
異常系なら処理やめてエラーを出せ
仕様決定のバランス
技術スタックも仕様も予めカッチリ決めておければまっすぐ進めるのですが、それだと初速までが遅くなるというジレンマがあります。
今回は以下のアプローチを取りました:
- 最低限の要件だけ決めて開発開始
- ベータテストで不足機能やバグを洗い出し
- 必要に応じて技術スタックも柔軟に変更
このやり方で初速を保ちながら、ユーザーフィードバックを素早く取り込むことができました。
デザインについて
今回はデザインも起こしていません(デザイナーのくせに)。
過去にTailwindでLPを作ってきた経験値を活かして、まさにバイブスで見た目を作りました。社内向けシステムなので、この割り切りが正解でした。
運用コスト
現在の運用コストはAPIを叩くLambdaの費用だけです。
- Supabase: 無料枠(PostgreSQL)
- Vercel: 無料枠(Next.jsホスティング)
- AWS Lambda: 従量課金(月数百円程度)
DBを構えるとなると色々手続きやら設定がありハードルが高かった時代と比べると、自分のようなプロパーでバックエンドをやってきていない人間にとっては良い時代になったと感じます。
Claude CodeでWebサービスを作るということ
初速の速さ
初速は驚くほど早く、なんとなく動くものを作るまではめちゃくちゃ早いです。
要件を伝えて数時間後には動くプロトタイプができている、という体験は従来の開発では考えられないスピード感でした。
デバッグフェーズの長さ
ただし、そこからのデバッグは永遠に感じられるぐらい長いです。
トンチンカンな実装をすぐやってしまうので、このフェイズから急速に実装者に負荷がかかり始めます。特に以下のような問題が頻発しました:
- 異常系と正常系の区別をClaude Codeが区別できていない
- 既存コードとの不整合や重複実装、勝手な補完
- パフォーマンスを考慮しない実装
長時間作業の注意点
特に、長めのプロンプトや要件定義などを伝えて寝る、起きるまでにE2Eまで完了させといてくれだと、マジで全く頼んでない仕様とかを追加されていることがめちゃくちゃあります。
朝起きて確認すると、以下のような事態に:
- 不要な新機能が勝手に追加されている
- UI/UXが勝手に変更されている
- データベーススキーマが変更されている
- 既存の動いていた機能が壊れている
- よく似た名前で別の機能が追加されている(既存実装の確認が漏れている)
結論: Claude Codeは短いイテレーションで細かく確認しながら進めるのがベストです。
まとめ
Claude Codeと二人三脚で社内Webサービスを開発した結果、以下の学びを得ました。
技術的な学び
- Next.js + Supabase + Vercel + Lambda の無料枠構成でも社内システムなら実用に耐え得る
- Flask → Next.js API Routes への移行でインフラが劇的に簡素化
- 明示的な指示(ポート番号、ページネーション、異常系処理、既存コード参照)が重要
Claude Code 活用のコツ
- CLAUDE.mdの安心度はお守り以下(どれだけしつこく「〜するな」と言ってもやってくる。)
-
settings.local.json の
"ask"
でツールに承認を要求(デプロイやSQL実行を防ぐ) - テストの粒度を明確に指定(E2Eテストまで求める。すぐにAPIテストが終わったので完了しましたと言ってくる。)
- 既存コードを参照させる(毎回ゼロから作らせない)
- サードパーティAPIの正常系/異常系を明示
- 短いイテレーションで進める(長時間放置すると予期しない変更を勝手に行う)
開発体制
- 実働約2ヶ月(5月スタート、9月から本格稼働)
- 運用コスト月数百円(ほぼ無料)
- デザイン未起こし(Tailwindでバイブス実装)
所感
Claude Codeは初速を最大化するツールとして非常に優秀です。
ただ、実際には結構苦労しました。心的疲労だけ見れば、初めてのそれなりの規模の開発だったからかもしれませんが、普通に自分でコード書いたのと大差なかったかもしれません。
結局のところ、AIが書いたコードを理解して修正するコストと、最初から自分で書くコストは、思ったより変わらないのかもしれないとすら思いましたが、まあそれでも掛かった時間で言えばやっぱり短いのは短いかもしれない。特にClaude Codeにお願いして、別の開発をその横で進められるというのは大きなメリットとも言えます。
また、AIだけではなく、技術スタックの選定や、インフラ構築のハードルが大幅に下がったことが中小規模の開発に追い風を与えているのは間違いありません。
Supabase + Vercel + Lambda の組み合わせで月数百円で動くシステムが作れるという知見は、今後に活きると思います。