NVIDIA Q1 FY27 書き起こしを作りながら、/blog の SPA キャッシュ・Breadcrumb・画像モーダル・SVG チャートをまとめて整備した日
NVIDIA が日本時間の夜中に Q1 FY27 決算を出した。過去 Q3 のときに作った全文翻訳の記事スタイルが手元に残っていたので、同じフォーマットで Q1 もまとめたかった。書き起こしを取りに行ったところから、サイト側の表示の粗が4つ立て続けに見つかって、結果として記事執筆と本体整備を同時並行で進めた日になった。
きっかけ:NVIDIA Q1 FY27 と Motley Fool の書き起こし
2026-05-20 のマーケット引け後に NVIDIA が決算発表をした。820 億ドルの売上で前年同期比 +85%、Hyperscale / ACIE / Edge という新しい3セグメント構成が出た。Vera CPU が 20B 規模、VeraRubin が Q3 量産入り、自社株買いの新枠 80B 承認、というあたりが目立った数字。
全文書き起こしのソースとして使っているのは Motley Fool の "Nvidia (NVDA) Q1 2027 Earnings Transcript"。過去 Q3 のときも同じソースから取っていて、トーン揃えのためにここに固定している。
全文取得:WebFetch が要約してくるので agent-browser に切り替え
最初に WebFetch でページを取りに行ったところ、出てきたテキストが要約版だった。Toshiya Hari の冒頭挨拶も、Colette Kress の財務パートも、ところどころ削れていて全文ではない。これでは翻訳の元にならないので、agent-browser に切り替えて自分のログイン済み Chrome 経由で取りに行ってもらった。
agent-browser open "https://www.fool.com/.../nvidia-nvda-q1-2027-earnings-call-transcript"
agent-browser eval "document.body.innerText"
agent-browser で innerText を抜き出すと、Toshiya Hari → Colette Kress → Jensen Huang → Q&A の構成がそのまま降ってきた。これを元に nvidia-fy27-q1-earnings.md に貼って、節ごとに日本語訳を当てていく作業に入った。
問題①:/blog 一覧で新記事が出ない(payload キャッシュ)
翻訳作業の途中で /blog をブラウザで開いて確認したら、SpaceX の S-1 サマリ記事と書きかけの NVIDIA 記事が一覧に出てこない。書いたファイルがそこにあるのに、一覧画面で見えない。スクショを並べて見比べて、ようやく違和感に気づいた。
.data/content.db(@nuxt/content の SQLite)には新しい記事がちゃんと入っている。直接クエリすると 1073 件返ってくる。それなのに /blog の一覧では 1064 件で止まっている。差分の 9 件がまさに直近で追加した記事群。
pages/blog.vue 側で useAsyncData を使っているのが原因だった。useAsyncData のデフォルト挙動として getCachedData が payload.data から先に読みに行く。dev サーバが返す /blog/_payload.json?dev が HTTP キャッシュに残っていて、ブラウザはそちらを信用してしまう。SQLite の側がいくら更新されていても、payload が古ければ古い結果が出る。
dev 環境では payload キャッシュを引かないように getCachedData を上書きして潰した。
const { data } = await useAsyncData('blog-articles', () => queryCollection('content').all(), {
getCachedData: import.meta.dev ? () => undefined : undefined,
})
ハードリロードして 1073 件に戻ったのを画面で確認した。1064 が 1073 に増えた瞬間にようやく息ができた。
問題②:/blog の Breadcrumb で Home がリンクにならない
一覧が戻ったので Breadcrumb を眺めたら、/blog で「Home」とだけ表示されていて、しかもそれがリンクになっていない。現在ページ扱いされていて、押せない。トップに戻りたいときに毎回ブラウザの戻るボタンを使う羽目になっていた。
Breadcrumb.vue のロジックを開いて、パスを / 区切りで分解して最後を current にする、という単純な実装になっていた。/blog だとセグメントが1つしかなくて、それがそのまま「現在ページ」になってリンクが消える。
「Home / 一覧」の2段にして、Home は常にリンク、最後のセグメントだけ current にする方針に変えた。ロジックは Vue コンポーネントに直書きしていたのを app/utils/breadcrumb.ts に切り出して、Vitest を 14 件追加した(ルート、深いパス、末尾スラッシュ、/blog 単体、日本語スラッグ、など)。pure function なのでテストが書きやすかったし、apps/web/app/utils/** がカバレッジ対象なので数字も動いた。
問題③:記事内画像のクリック拡大モーダル
NVIDIA 記事に SVG チャートを差し込み始めたところで、画像が小さくて細部が読めない、というのに気づいた。クリックで拡大したい。
apps/web/app/components/content/ProseImg.vue を新規で作って、@nuxt/content の MDC が記事内の <img> を自動でこのコンポーネントに置き換える仕組みに乗せた。ホバーで 1.5% だけ拡大して薄い影を出す、クリックで Teleport で body 直下にモーダルを出して全画面、Escape で閉じる。
最初の実装で 1 回ハマった。<img> を <span> で包んで inline-block にした結果、中の SVG が intrinsic size を失って 2px × 2px に潰れた。SVG 側に明示的な width/height 属性が無かったのが原因。wrapper の <span> を排除して <img> を素のまま出すように戻し、SVG ファイルの <svg> タグに width/height を書き足した。
モーダル側でも詰まりがあって、最初は width: auto; height: auto にしていたら viewport の真ん中で小さく表示されてしまった。viewport いっぱいに広げたかったので max-width: 95vw; max-height: 95vh に書き換えて、画像の大きさに引っ張られないようにした。
問題④:セグメント別売上 SVG チャート
NVIDIA がこの四半期から Compute / Networking から Hyperscale / ACIE / Edge にセグメントを切り替えた。文章で書いても伝わらないので、SVG チャートを4枚作って記事に差し込むことにした。
nvidia-revenue-stacked.svg:四半期売上の総額推移を積み上げ棒でnvidia-revenue-grouped.svg:セグメント別に棒を分離して並べたものnvidia-revenue-qoq-growth.svg:QoQ 成長率を右軸の折れ線でnvidia-revenue-yoy-growth.svg:YoY 成長率を同じく折れ線で
SVG を生成 → apps/web/content/2026-05/2026-05-22/ に配置 → 本文に  を書く、という流れ。配置しても dev server の watcher が拾ってくれない瞬間が何度かあって、touch nvidia-fy27-q1-earnings.md で本文ファイルを叩き直すと再認識した。Windows + Nuxt のファイルウォッチがたまに取りこぼす癖を、毎回 touch でなだめている。
フォントの違いにも途中で気づいた。SVG のテキストが、本体サイトの本文フォントとずれて少し細く見える。SVG 側に font-family を明示していなかったのが原因で、-apple-system, BlinkMacSystemFont, "Segoe UI", ... をルート <svg> に当てて統一した。
コミットと公開状態
1Password Environments の整理記事は別件で先にコミットを切った(f8a6ee0a content(2026-05-22): 1Password Environments MCP と CLI op run の整理記事を追加)。NVIDIA Q1 FY27 の書き起こし本体は、出典の扱いを整えるまで一旦 unpublished に倒している。表示まわりの整備(payload キャッシュ、Breadcrumb、ProseImg、SVG 表示)はこの記事側の見栄えにそのまま効いていて、後で publish に戻したときに最初から綺麗な状態で出る。
振り返り:違和感を拾う係と直す係
今日の4つは、全部「画面を見て違和感を拾ったのは自分、直したのは Claude Code」という構図だった。
- 1064 と 1073 の差を見比べて「あれ、新しい記事が出てない」と気づいたのは目視
- Breadcrumb の Home が押せないことに気づいたのも実際に押そうとした手
- SVG が 2x2 に潰れているのも、画面を開いて点が見えた瞬間
- フォントが本体と違うことに気づいたのも、横に並べた目視
直す手順は Claude Code に流して全部やってもらった。useAsyncData のキャッシュ無効化も、Breadcrumb のリファクタもテスト追加も、ProseImg のモーダル実装も、SVG の生成も。人間は違和感を拾う係、AI は実行係。この役割分担が一番事故りにくい、という当たり前のことを今日も体感した。
明日以降の積み残しとしては、/blog 一覧のキャッシュ問題は dev だけ潰した状態で、SSG ビルド側の payload 生成タイミングがズレた場合の挙動はまだ詰めていない。production で同じ症状が出る可能性があるので、pnpm generate の最終確認のときに 1073 件が一覧に出ているかを画面で確認する手順を入れておく。