エージェントに「Next.js のページを直して、ブラウザで開いた状態を見せて」と頼んだ後、Manager Surface には「Started dev server on port 3000」と表示されているのに、Antigravity の埋め込みブラウザだけが真っ白なまま。Walkthrough にも「http://localhost:3000 を確認」と書かれているので、念のため外部ブラウザで開くと普通に動く。何が起きているのか気になりますよね。
この症状は Antigravity のブラウザプレビューでは比較的よく起きます。原因はだいたい3つに集約できますが、慌てて再起動を繰り返すよりも、最初に「真っ白の種類」を見極めるだけで調査範囲が一気に絞れます。私自身、開発中に何度か同じ状況にぶつかってきましたが、診断の順序を決めてからは数分で原因にたどり着けるようになりました。ここでは症状ごとの切り分け方と、再発を防ぐ設定の見直し方を整理しておきます。
ブラウザプレビューが返してくる「真っ白」は3種類ある
「真っ白」と一口に言っても、実は3つの別々の状態が混ざっています。最初にどれに該当するかを見極めるのが診断の出発点です。
- HTML は届いているが見た目だけ空 — ビューソースを見ると
<html><body></body></html>のような空の構造が返っています。ビルドエラー・JS 実行エラー・SSR の失敗が典型 - 接続そのものが確立していない — 「Connection refused」「Failed to fetch」が表示される、または無限ローディングが続く。dev サーバーが該当ポートで待ち受けていない
- 接続はできているが Antigravity 側で表示できない — Content-Security-Policy の
frame-ancestorsかX-Frame-Options: DENYで iframe 内の描画が拒否されている
この3つを見分ける一番手早い方法は、プレビューパネルの右上にある「Open in external browser」で同じ URL を外部ブラウザで開いてしまうことです。
- 外部ブラウザでも空白 → アプリ側の問題(パターン1)
- 外部ブラウザではエラー → 接続の問題(パターン2)
- 外部ブラウザでは正常 → 埋め込み側の制約(パターン3)
この30秒の判定を最初に挟むだけで、無駄な dev サーバー再起動が大幅に減ります。
パターン1 — HTML が届いているのに空白の場合
外部ブラウザでも真っ白なら、ほぼ確実にアプリ側の問題です。ここでは次の順で確認しています。
まず、Manager Surface のターミナル出力を最後まで遡ってみてください。エージェントは「Started server」のログを見て成功扱いにしますが、その直後に Webpack や Vite が compile error を出していることは珍しくありません。エージェントは自分のターミナルに流れていったエラーを意外と見落とします。
次に、ブラウザプレビューの右上「Inspect」(または ⌘ + Option + I)で DevTools を開き、Console と Network タブを見ます。Hydration mismatch やモジュール読み込み失敗(404 が混ざっているケース)が典型です。
最後に、配信内容を直接確認します。
# dev サーバーが返している HTML を覗く
curl -s http://localhost:3000 | head -50<div id="root"></div> のような空のマウントポイントが返っていれば、配信自体は OK です。中身が空なら SSR/SSG が失敗しているので、エージェントに「直近のコンパイルエラーをログから抽出して、原因のファイルを直して」と明示的に依頼するのが手早く解決する道です。エージェントは自分が出したエラーを忘れがちなので、こちらから「ログを見直してくれ」と一度投げ直す方が確実に直ります。
パターン2 — そもそも接続できない場合
「Connection refused」「ERR_CONNECTION_REFUSED」が出ている時の確認順序です。
ひとつ目は、エージェントが指示しているポートを再確認することです。Walkthrough に「localhost:3000 を確認」と書かれていても、実際には Vite が 5173 で立ち上がっていることがあります。フレームワークごとのデフォルトポートを覚えておくと、ここで詰まらなくなります(Next.js: 3000 / Vite: 5173 / Remix: 3000 / Nuxt: 3000 / Astro: 4321)。
ふたつ目は、ポートの競合確認です。
# macOS / Linux で 3000 番を使っているプロセスを特定
lsof -i :3000
# Windows (PowerShell)
Get-NetTCPConnection -LocalPort 3000別のプロセスが既にバインドしていると、新しい dev サーバーは黙って別ポートに逃げます。エージェントは「移動した」事実を Walkthrough には反映してくれないことがあるので、出力ログの末尾で実ポート番号を必ず確認してください。
みっつ目は、localhost バインドの罠です。Vite は標準で 127.0.0.1 にしかバインドしないので、Antigravity の埋め込みブラウザが別のホスト名で接続しようとすると弾かれることがあります。私はこの設定をデフォルトで入れるようにしています。
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
server: {
host: true, // 0.0.0.0 にバインドして埋め込みブラウザからもアクセス可能にする
port: 5173,
strictPort: true, // ポート競合時に黙って別ポートへ逃げないようにする
},
});Next.js の場合は、package.json の dev スクリプトを next dev -H 0.0.0.0 -p 3000 に書き換えるのが同等の対応です。strictPort 相当のオプションは Next には無いので、ポート競合のリスクは別途 lsof で確認しておきます。
パターン3 — iframe で表示できない場合(CSP の壁)
外部ブラウザでは普通に動くのに、Antigravity のプレビューだけが真っ白という時は、ほぼ間違いなく Content-Security-Policy の frame-ancestors か X-Frame-Options: DENY が原因です。Express + Helmet・Cloudflare Pages・Vercel のデフォルトがこれを返すケースをよく見かけます。
DevTools の Console を開くと、こんな警告が出ているはずです。
Refused to display 'http://localhost:3000/' in a frame because an
ancestor violates the following Content Security Policy directive:
"frame-ancestors 'self'".
ローカル開発時のみ、フレーム埋め込みを許可する設定を入れます。Express + Helmet の例です。
// server.js(開発時のみ緩める)
import helmet from 'helmet';
app.use(
helmet({
contentSecurityPolicy:
process.env.NODE_ENV === 'production'
? undefined // 本番は厳格な CSP を保つ
: {
directives: {
'frame-ancestors': [
"'self'",
'http://localhost:*',
'http://127.0.0.1:*',
],
},
},
crossOriginEmbedderPolicy: false, // 埋め込み描画が崩れる場合のみ
})
);本番ビルドで CSP を緩めるのは絶対に避けてください。私はこの種の設定を入れる時、ファイル冒頭に // DEV ONLY のコメントを大きめに入れて、誤って本番に持ち込まないようにしています。
それでも直らない時の最終チェックリスト
ここまでの対処で直らない時に、最後に通る5つの確認ポイントです。
ひとつ目は、dev サーバーをエージェントから切り離して手動起動してみることです。Antigravity のターミナルで npm run dev を直接叩き、同じポートを外部ブラウザで開いてアクセスできるか確認します。エージェントの管理プロセスがハングしているだけ、ということがあります。
ふたつ目は、/etc/hosts の localhost 行が消えていないかの確認です。macOS でセキュリティソフトが書き換えてしまう事故が地味に発生します。
みっつ目は、VPN とプロキシを一時的に切ることです。corporate proxy 経由で localhost が解決できなくなるパターンは、思い出した時に最初に試す価値があります。詳しい対処は Antigravity の企業プロキシ・ファイアウォール接続問題の解決 にまとめてあります。
よっつ目は、Antigravity の埋め込みブラウザを一度閉じてから再オープンすることです。タブのキャッシュが原因という単純なケースもあります。
最後は、プロジェクトを開き直すことです。内部の preview proxy がハングしている時は、ワークスペースを閉じて開き直すと回復することが多いです。
再発を防ぐためにプロジェクトに入れておく設定
ここまでの内容を踏まえて、新規プロジェクトを作る時に最初から入れておくと安心な設定をまとめておきます。
package.jsonの dev スクリプトで-H 0.0.0.0または--hostを必ず指定するvite.config.ts/next.config.tsなどでserver.host: trueとserver.strictPort: trueをセットにする(ポートが暗黙に変わるのを防げます)- 開発時の CSP は
frame-ancestorsを緩める。本番ビルド時のみ厳格化する - AGENTS.md に「dev サーバーは 0.0.0.0 でバインドする」「Walkthrough には実際に bind されたポート番号を必ず書く」と明示しておく
エージェントが Walkthrough にポート番号を書いてくれるかどうかは、AGENTS.md の指示でかなり変わります。私は「サーバー起動後は必ず lsof -i :ポート を 1 度実行して、その出力を Walkthrough に貼ること」というルールを入れています。
全体を振り返って
ブラウザプレビューが真っ白になったら、まず「外部ブラウザで開いて確認」の30秒テストを1回挟むだけで、調査範囲がぐっと狭まります。今日のうちに着手できる一歩としては、現在開いているプロジェクトの dev スクリプトに -H 0.0.0.0 を加えてコミットしておくのが効果的です。次に同じ症状が出たとき、「接続の問題」を最初から候補から外せるようになります。
Walkthrough 自体が空白になる症状は別の原因なので、そちらは Antigravity の Walkthrough が表示されない・空になる時の対処法 を参考にしてみてください。プレビューと Walkthrough は表裏一体の機能ですが、原因の切り分けが違うので、合わせて読んでおくと診断のスピードが上がります。
ブラウザと dev サーバーの間で何が起きているかが頭の中でつながると、CSP・CORS・iframe の話が一段わかりやすくなります。