事例・基礎知識
UIはあるのに公開できない"あるある"7選(原因→対処)
UIはあるのに公開できない原因を7つに整理し、それぞれの対処法を紹介します。認証・データ設計・監視など見落としポイントを解説。
「UIはもうできています。あとは公開するだけです」
この言葉を聞くたびに、少し身構える。なぜなら、その「あとは公開するだけ」の部分に、平均すると3〜6週間分の作業が眠っていることが多いからだ。
CursorやLovable、Bolt.newといったAIコーディングツールの登場で、見た目の整ったUIを作るハードルは劇的に下がった。1週間でそれなりのプロダクトが形になる。問題は、「動いて見える」状態と「公開できる」状態が、まったく別物だということだ。
本番公開に詰まる理由には、実はパターンがある。7つのブロッカーに整理したので、自分のプロジェクトに照らし合わせながら読んでほしい。
7つのブロッカー早見表
| # | ブロッカー | 解決にかかる時間の目安 | 見落とし頻度 |
|---|---|---|---|
| 1 | 認証がない | 1〜3日 | 非常に多い |
| 2 | データ設計がない | 3〜7日 | 多い |
| 3 | 外部APIが未確定 | 1〜2週間 | 多い |
| 4 | 監視がない | 半日〜1日 | 非常に多い |
| 5 | 運用者が決まっていない | 1〜2日(体制整備) | 中程度 |
| 6 | 引き継ぎ資料がない | 1〜3日 | 非常に多い |
| 7 | スコープが揺れている | 1〜2週間(方針決定) | 多い |
ブロッカー1:認証がない
こんな状況に心当たりはないか
CursorでSNSアプリを作った。投稿、いいね、フォロー機能が全部動く。デモをしたら「すごい!」と好評だった。さあ公開しようとしたとき、気づく。「ログイン画面がない。誰でも誰の投稿でも削除できる」。
AIツールはUIコンポーネントを作るのが得意だ。しかし認証は「見た目」ではなく「裏側のロジック」なので、明示的に指示しないと後回しになりやすい。v0やLovableが生成したUIには、ログインフォームのデザインはあっても、セッション管理やルート保護が実装されていないことが珍しくない。
具体的な対処
Clerkを使えば1日で解決できる。npx create-next-appで作ったプロジェクトにClerkを導入する場合、公式ドキュメント通りに進めれば最短2〜3時間でGoogleログインが動く。Next.jsのミドルウェアにauthMiddlewareを1行追加するだけで、未認証ユーザーをログインページにリダイレクトできる。
Supabase AuthでもGoogleログインは設定できるが、RLS(行レベルセキュリティ)のポリシーも合わせて設定しないと、ログイン後も他ユーザーのデータが見える状態になる。認証を実装したら「別アカウントを2つ作って、一方から他方のデータに触れるか」を必ず確認すること。
解決の目安:1〜3日
ブロッカー2:データ設計がない
こんな状況に心当たりはないか
UIライブラリのデモコードをベースに作ったアプリがある。ダッシュボードはきれいだし、グラフも動く。しかしよく見ると、すべてのデータがconst mockData = [...]というハードコードだ。本番では誰のデータも保存されない。
AIが生成するコードには、フロントエンドの動作確認用にモックデータが含まれていることが多い。そのままデプロイしても、ユーザーが何かを入力しても、データはどこにも残らない。
具体的な対処
まず「何を保存する必要があるか」をテーブル単位でリストアップする。ユーザーテーブル、投稿テーブル、コメントテーブル……という具合だ。それぞれのカラムと型を決め、Supabaseのテーブルエディタで実際に作る。次に、モックデータを参照していた箇所を、Supabaseへのselect・insert・update・deleteに置き換えていく。
この作業は地味だが、モックデータの件数が多いほど時間がかかる。10画面以上あるアプリだと1週間かかることもある。公開前にモックデータを検索して(grep -r "mockData" src/)、全件置き換えが完了しているか確認しよう。
解決の目安:3〜7日
ブロッカー3:外部APIが未確定
こんな状況に心当たりはないか
「決済はStripeで実装済みです」と言うが、よく聞くとWebhookのエンドポイントがlocalhost(開発用アドレス)のままだ。本番のドメインに変えていない。SendGridのメール送信機能も、ドメイン認証(SPF/DKIM)を通していないので、送ったメールが全部迷惑メールに入る。
外部APIはローカル開発環境での動作確認が難しいため、テスト環境の設定のまま放置されやすい。StripeにはTestモードとLiveモードがあるが、切り替えを忘れたまま公開すると実際の課金が一切発生しない。
具体的な対処
外部APIを使っている箇所を全部リストアップし、各サービスの本番用設定を個別に確認する。
- Stripe: Webhookのエンドポイントを本番URLに更新。APIキーをTestキーからLiveキーに差し替え。本番の決済テストを実際に1件流して確認する
- SendGrid: ドメイン認証(SPFレコードとDKIMレコードをDNSに追加)を完了させる。認証なしで送信したメールはGmailの迷惑メールに高確率で入る
- Google Maps, Twilio等: APIキーに本番ドメインの制限をかける(開発中は無制限にしていることが多い)
ドメイン認証はDNSの反映待ちで24〜48時間かかる場合がある。公開日から逆算して早めに着手すること。
解決の目安:1〜2週間(DNS反映待ち含む)
ブロッカー4:監視がない
こんな状況に心当たりはないか
公開して3日後、ユーザーから「投稿が保存されない」という連絡が来る。調べてみると、2日前からエラーが出ていた。その間に10人がサービスを使い、何も保存されないまま離脱していた。エラーに誰も気づいていなかった。
監視ツールを入れていないと、ユーザーからの報告が唯一の検知手段になる。しかし黙って離脱するユーザーのほうが圧倒的に多い。報告してくれる人は1割もいない。
具体的な対処
Sentryを使えば半日で導入できる。Next.jsプロジェクトならnpx @sentry/wizard@latest -i nextjsを実行するだけで設定ファイルが自動生成される。エラーが発生するとSlackやメールに通知が届くように設定できる。月5,000エラーまでは無料枠で対応できる。
最低限これだけは入れておきたい。
- Sentry(エラー検知・通知):無料枠あり
- Vercelのアナリティクス(ページビューの確認):無料枠あり
- UptimeRobot(サービスが落ちたら通知):無料で5サイトまで監視可能
監視がないまま公開するのは、車のダッシュボードを全部テープで隠して走るようなものだ。何かが起きても、ユーザーが教えてくれるまでわからない。
解決の目安:半日〜1日
ブロッカー5:運用者が決まっていない
こんな状況に心当たりはないか
代表と開発者が同一人物のケースは多い。その場合、その人が急病や旅行で2週間不在になったとき、サービスが止まっても誰も対応できない。問い合わせへの返信もできない。パスワードを知っているのが1人しかいない状態で本番公開するのは、単点障害を抱えたまま走るようなものだ。
また「運用者」の問題は規模が大きくなると複雑になる。本番DBに直接触れる人は誰か。緊急連絡先はどこか。インシデント対応のフローがないと、問題が起きたとき場当たり的な対応になって二次被害が出やすい。
具体的な対処
最低限、以下を整理しておく。
- 各サービスの管理アカウントを2人以上で共有する(1Password等のパスワードマネージャーを使う)
- 緊急時の連絡先と対応手順を1枚の紙にまとめる(「サーバーが落ちたら→まずVercelのダッシュボードを確認→Supabaseのステータスページを確認→それでも不明なら●●に連絡」)
- 自分以外の1人に最低限の操作を教える(管理画面の見方、ユーザーへの通知方法)
解決の目安:1〜2日(体制整備)
ブロッカー6:引き継ぎ資料がない
こんな状況に心当たりはないか
AIに「このコードは何をしていますか?」と聞いたら「わかりません」と返ってきた。AIが生成したコードを積み上げてきたが、全体の構造を誰も把握していない状態だ。環境変数が20個あるが、どれが何のためのキーかわからない。.env.exampleも残っていない。
1ヶ月後に自分のコードが読めなくなる、というのはAI生成コードでよく起きる。AIはコンテキストなく次々とコードを追加するので、プロジェクト全体の設計方針が見えにくくなりがちだ。
具体的な対処
公開前に最低限これだけ作る。
- README.mdに「このアプリは何をするものか」を3行で書く
.env.exampleを作り、環境変数の名前と用途を列挙する(値は書かない)- デプロイ手順を箇条書きにする(
npm run buildして何をどこに設定するか) - 主要なテーブルの一覧と役割をコメントかドキュメントに残す
完璧なドキュメントは不要だ。「初めて見た人が30分でローカル環境を立ち上げられる」レベルで十分。書くのに1〜3日かかるが、後から見返したとき何十倍もの価値を発揮する。
解決の目安:1〜3日
ブロッカー7:スコープが揺れている
こんな状況に心当たりはないか
「やっぱりこの機能も必要ですよね」という会話が毎週起きる。最初は「投稿と閲覧だけ」だったはずが、「通知機能」「分析ダッシュボード」「CSVエクスポート」が追加され、3ヶ月経っても公開できていない。
AIツールは機能追加のコストを下げすぎた。「これもすぐ作れそう」という感覚で追加し続けた結果、MVP(最小限の製品)の定義が消えてしまう。公開判断の基準がないので、いつまでも「もう少し」が続く。
具体的な対処
公開判断の基準を先に決める。「この3つの機能が動けば公開する」と決めたら、それ以外の機能追加要望はリストに追加するだけにして実装しない。
具体的には、Notionやスプレッドシートに「MVP必須機能」「v1.1以降に追加」「検討中」の3列を作り、全機能をどれかに分類する。MVPの必須機能は5個以内に絞る。それ以上になってきたら「どれを外せるか」を議論する。
公開後にフィードバックをもらってから作る機能は、公開前に作っても無駄になることが多い。完璧なv1より、動くβ版を早く出すほうが検証コストが低い。
解決の目安:1〜2週間(意思決定のプロセスを含む)
「全部リリース1週間前に気づく」というパターン
上の7つに共通するのは、「UI開発中は問題が見えない」という点だ。
認証がなくても、開発中は自分しか使わないから気にならない。データ設計が甘くても、モックデータが動いているから問題に見えない。外部APIの本番設定が済んでいなくても、テスト環境では動く。
問題が顕在化するのは「公開直前に本番環境を触り始めたとき」だ。そのタイミングで7つ全部が一気に浮き上がり、「1週間で全部やらなきゃ」という状態になる。
これは能力の問題ではない。AIツールがUI作成を最適化しすぎた結果、「UIができた=完成に近い」という錯覚が生まれやすくなっている構造的な問題だ。
公開前セルフ監査:10分でできる確認リスト
公開の前に、以下を一度確認してほしい。
認証・セキュリティ
- ログインなしではアクセスできないページが、実際にアクセス制御されているか
- 別アカウントを作って、他ユーザーのデータに触れないか確認したか
- APIキーや秘密情報がコードに直書きされていないか(
grep -r "sk-\|api_key\|secret" src/) -
.envが.gitignoreに含まれているか
データ・API
- モックデータが残っていないか(
grep -r "mockData\|dummyData\|sampleData" src/) - 外部APIのキーが本番用になっているか
- StripeのWebhookが本番URLを向いているか
監視・運用
- エラー監視ツール(Sentry等)が入っているか
- パスワードや認証情報を自分以外の1人と共有しているか
- 環境変数の一覧と用途が
.env.exampleに残っているか
スコープ
- 「これが動けば公開する」という機能リストが3〜5個に絞られているか
- 公開日が決まっているか
UIが完成していることは素晴らしい。しかしそれは「出発点に立った」状態だ。上の7つを一つずつ潰していくことで、「公開できる」状態になる。
自力で全部やるのが難しければ、チェックだけ外部に頼むという選択肢もある。コード全体を書き直す必要はない。問題箇所を特定して、優先度の高い順に片づけるだけでいい。