ブログ
Web 制作・システム開発に関する記事を公開しています。
Gemini Live API の音声応答が 6 秒遅れる原因は thinking
Gemini Live API の native audio モデルで、テキストを送ってから音声が返るまでの初動が最大 6 秒かかっていました。原因はモデルの地力ではなく、思考モード(thinking)が既定で有効なことです。thinkingBudget: 0 を指定すると初動の中央値は 976ms、最悪値も 1.3 秒に収まりました。preview 2 モデルでの実測データ付きです。
navigator.share の判定だけでは PC でも共有シートが出る
スマホでシェアボタンを押すとログインを求められるので、共有シートに切り替えたところ、PC でも切り替わりました。Chrome・Safari・Edge はデスクトップでも Web Share API に対応しているためです。日本語で流通している判定方法は navigator.share の存在チェックですが、これは Chrome デスクトップが非対応だった頃の前提で、今はスマホかどうかの判定になりません。(pointer: coarse) と組み合わせてスマホだけに共有シートを出します。
WordPress 移行後に本文に残った旧 URL を Portable Text から数える
WordPress から移行したあとに残る旧画像 URL を片付けようとして、公開 HTML から数えた 21 本とデータベースから数えた 58 本が食い違いました。差の正体は表示されないリンク注釈と、生 HTML ブロックの中の書き換え漏れでした。ついでに 5 記事で画像が 404 になっていたことも見つかりました。
Astro の routeRules から外してもページがキャッシュされる
エッジキャッシュから問い合わせページを外そうとして routeRules に書かずにデプロイしたら、本番では HIT が返ってきました。キャッシュの有効判定は maxAge かタグのどちらかで立ち、CMS のキャッシュヒントはタグだけを持つため、保持時間の指定が無いままキャッシュされます。外すには routeRules ではなくページ側の Astro.cache.set(false) が要ります。
Cloudflare で purge しても age が伸び続けるのは壊れていない
記事を更新してもページが変わらず、age が単調増加する。ここから「失効が壊れている」と結論しましたが、間違いでした。purge はキャッシュを消すだけで、再描画は次のアクセス時です。curl -I での確認はキャッシュから返るためサーバーに届きません。4 回続けて誤診した過程と、キャッシュのデバッグで守るべきことをまとめます。
Cloudflare で HTML がキャッシュされないのは既定の仕様
「Cloudflare を通しているからキャッシュは効いている」は静的ファイルの話でした。HTML には cf-cache-status ヘッダすら付きません。キャッシュミスではなく、判定の対象になっていない状態です。既定が拡張子ベースである理由と、Astro のサーバーレンダリングで HTML をエッジにキャッシュさせる方法を実測とあわせて書きます。
Cloudflare Workers 無料プランで 503 が出る原因は CPU 上限
毎分 10〜31 リクエストという低負荷で 4 回に 1 回が 503。同じサイトが 1 時間 2,516 リクエストをエラーゼロで捌いた実績もあり、負荷では説明が付きません。原因は無料プランの CPU 上限 10ms でしたが、この上限は「1 リクエストで超えたら落ちる」という単純な仕組みにはなっていません。実測ログとあわせて機構を整理します。
Cloudflare Workers 無料プランの 3 MB 上限に数えられるもの
Cloudflare Workers の無料プランには gzip 後 3 MB というバンドルサイズ上限があります。実運用中のサイトの実測値は約 2.1 MB で、残る余裕は 900 KB ほど。画像生成ライブラリを 1 つ足すだけで +680 KB 増えて 3 MB の上限の手前まで届く一方、11 MB ある静的アセットは 1 バイトも数えられません。何が数えられて何が数えられないのかを実測値で整理します。
WordPress の WXR エクスポートに画像が含まれない
WordPress のエクスポート機能が吐く WXR ファイルに画像のバイナリは含まれず、旧サーバーを解約すると原本ごと消えます。移行直後は完了に見えてしまう理由と事前チェックリスト、そして手遅れだった場合に Wayback Machine から 36 件の画像を実際に回収した手順・落とし穴・法とマナーの線引きをまとめます。
Node.js で favicon.ico を生成する。sharp は ICO を書き出せない
Node.js 画像処理のデファクトである sharp は ICO を出力できず、BMP 格納の ICO は読み込みすらできません。しかし ICO は 6 バイトのヘッダと 16 バイト × N の目次に PNG を並べるだけの単純なコンテナで、追加依存ゼロ・約 30 行で手組みできます。マルチサイズ favicon.ico を生成する実装と細部の注意をまとめます。
Google 検索結果の favicon が地球儀のままになる原因は robots.txt
favicon はブラウザのタブに表示されているのに、Google 検索結果ではデフォルトの地球儀アイコンのまま — 原因は robots.txt が favicon の配信 URL をブロックしていたことでした。ヘッドレス CMS やサイトビルダーの構成で構造的に起きるこの問題の診断手順と、静的 /favicon.ico 併設による対策をまとめます。
Astro.rewrite(\"/404\") が 200 を返してソフト 404 になる
Astro SSR の動的ルートでエントリ未検出時に Astro.redirect(\"/404\") すると 302、Astro.rewrite(\"/404\") にしても HTTP ステータスは 200 になりソフト404になります。Astro が rewrite でステータスを 200 にリセットする機構(astro@7.0.7 のソース)と、404.astro 側で Astro.response.status = 404 を立てて正しく 404 を返す方法をまとめます。
WordPress 移行後に記事内の画像が 404 になるときの対処
WordPress をヘッドレス CMS へ移行したあと、本文が旧 /wp-content/uploads/ を参照したままで記事内の画像が 404 になる問題。404 の 9 割超は実体が移行済みで URL だけが古いので、本文を書き換えずキャッチオール動的ルート 1 本でファイル名からメディアを引いて 301 する設計と、WordPress 命名(-WxH サムネイル・-e 編集版)や .gitignore の落とし穴をまとめます。
D1 の無駄なクエリを削ったらクエリ数が増えた原因
エッジ SSR(Cloudflare Workers + D1)ではレイテンシの支配項は CPU ではなく DB への往復回数です。明らかに無駄なクエリを削ったら本数が 19→22 に増えた原因であるリクエスト内キャッシュの重複排除と、推測で書き換えず「表示が変わっていないこと」を HTML のバイト一致で証明しながら最適化するウォーム A/B 計測の手順をまとめます。
Claude Code のサブエージェント並列でサイト群を保守する
AI コーディングエージェントを「司令塔 + 並列の実働班」に編成し、本番の複数サイトを日々保守している運用の設計を書きます。git worktree での物理分離、指示書に埋め込む計測プロトコル、権限の非対称、司令塔による二重検証、人間の介入点の切り分け。実際に出荷を止めたガードレールや、報告と実体の乖離といった実例と、この方式の限界まで含めてまとめます。
Google Analytics を入れずに Cloudflare でブログを監視する
ブログ運用の一次監視に欲しいのは「配信が壊れていないか」で、その情報は GA4(gtag.js)を入れなくても取れます。GA4 のクライアント計測とは別レイヤーの Cloudflare エッジ計測(GraphQL Analytics API の httpRequestsAdaptiveGroups)を GitHub Actions で定期実行し、死活チェック・週次レポート・Issue 自動起票までを組む監視設計を、GA との役割分担つきでまとめます。
AI エージェントを自走させるのはプロンプトではなくハーネス
AI コーディングエージェントの自律性を支えるのは長い指示書ではなく、成果物を機械的・決定的に合否判定する検証系(ハーネス)です。LLM は確率的、ハーネスは決定的というこの非対称を、決定的パイプライン・Claude Code の Hooks・ドメイン固有の検証プロトコル・観測とフィードバック・権限という5つの層に整理し、人間の介入点をどう絞るかを実運用の事実に沿ってまとめます。
Claude Code のチーム機能とサブエージェントの使い分け
「チーム機能はエージェント同士が P2P で連携できる。サブエージェントは親に報告するだけ。なら常にチームが上位互換では?」という直感に、両者の機構の違いから答えます。サブエージェント並列を実務で回している立場から、指示書が書けるか否かという一本の判断基準まで整理しました。
DNS が古い環境からドメイン切り替え直後のサイトを確認する
ドメイン切り替え直後、手元の DNS キャッシュやプロキシが古い IP を返して検証にならないとき、DoH(dns.google/resolve)で権威側の現在値を引き、curl --connect-to で名前解決だけ上書きして SNI・証明書検証込みの本番同様の確認をする手順をまとめます。
Tailwind v3 で node_modules の CSS が @layer エラーになる原因
Tailwind v3 を PostCSS 経由で入れると、node_modules のビルド済み CSS まで処理対象になり、ネイティブの @layer を使う標準準拠の第三者 CSS がエラーになります。管理画面が 500 になった実例から、@tailwindcss/vite(v4)移行による解決と、実際に必要だったクラス名の書き換えをまとめます。