◉ANTIGRAVITY LABEN
記事一覧/アプリ開発
▣ アプリ開発/2026-06-23上級

シェア画像の日本語だけが □ になる — Antigravity に next/og の CJK フォント供給を直させた実装メモ

next/og の ImageResponse で日本語タイトルだけが豆腐(□)になる。原因の Satori と woff2 の関係を解きほぐし、Google Fonts の text= サブセットをエッジで軽量に引き当てる実装を、Antigravity に直させる手順とあわせて記録します。

next-ogSatoriOGPedge-runtimeAntigravity377

✦ プレミアム記事

先日、Antigravity Lab に新しい記事を公開して、いつものように X とスレッズにリンクを貼りました。プレビューに出てきたシェア画像を見て、手が止まりました。英語の補助テキストは綺麗に出ているのに、肝心の日本語タイトルだけが、四角い豆腐(□□□□)の行列になっていたのです。

個人開発で複数のサイトを回していると、こういう「片方の言語だけ静かに壊れている」不具合がいちばん厄介です。エラーは出ません。ビルドも通ります。ただ、共有されたときにだけ恥ずかしい姿で世に出ていきます。

ここでは、その豆腐を退治するまでの実装を、つまずいた順に残します。題材は next/og の ImageResponse ですが、本質は「Antigravity のようなエージェントに OG 画像ルートを書かせると、ほぼ必ずこの罠に落ちる。なぜ落ちるのか、どう直させるのか」という一点に集約されます。

静かに失敗していたのは、フォントを渡していなかったから

最初のルートは Antigravity に書かせました。指示は素朴で、「記事タイトルを大きく入れた 1200×630 の OG 画像を opengraph-image.tsx で返して」というものです。エージェントは数秒で、いかにも正しそうなコードを出してきました。<div> を並べてタイトルを流し込み、ImageResponse で返すだけ。ローカルの英語タイトルでは、確かに描画されました。

ところが日本語が豆腐になる。ここで多くの方が font-family の指定を疑いますが、原因はもっと手前にあります。

ImageResponse の内部は Satori という、HTML/CSS を SVG に変換するエンジンです。そして Satori は、自分でフォントを一切同梱しません。fonts 配列で明示的に渡されたフォントの中に該当するグリフが無ければ、その文字は黙って欠落します。ラテン文字が出ていたのは、Satori が内蔵で持っているごく基本的な字形にたまたま含まれていたからで、日本語は最初から「持っていない字」だったわけです。

エージェントが出したコードには fonts の指定がありませんでした。エラーにならないので、エージェント自身も「成功した」と判断してしまう。ここが、人間が一度は目で確かめないといけない境界です。

woff2 を渡しても直らない、という二段目の罠

「ではフォントを渡せばいい」と、Antigravity に fonts を追加させると、今度は別の壁に当たります。多くのエージェントは、よくある書き方として Google Fonts の woff2 を fetch して渡そうとします。これも静かに失敗します。

理由は、Satori(および内部のラスタライザ)は woff2 を解釈できないからです。woff2 は Brotli で圧縮されたフォント形式で、Satori が直接読めるのは TrueType(ttf)・OpenType(otf)・woff までです。woff2 を渡すと、描画されないか、ランタイムによっては例外で落ちます。

ここを表で整理しておきます。

形式Satori で使えるか典型的な入手元備考
woff2不可ブラウザ向け Google FontsBrotli 圧縮。最も配られやすいが Satori は読めない
woff可一部 CDN読めるが入手しづらい
ttf / otf可css2 をサーバから取得本記事で使う。サブセットも効く

つまり目標は明確です。「描画する日本語の字だけを含んだ TrueType を、エッジで軽量に手に入れる」こと。Noto Sans JP のフルセットは数 MB あり、リクエストのたびに丸ごと取り寄せるのは現実的ではありません。必要なのは、タイトルに出てくる十数文字だけです。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦ImageResponse で日本語が □ になる本当の原因(Satori が woff2 を解釈できない)と、TrueType サブセットを引き当てる完全な実装
✦Google Fonts の css2?text= で描画する文字だけを取り寄せ、数十 KB でエッジ描画するコードと、固定ラベルまで含めたサブセット設計
✦文字溢れを Satori の制約内で潰す手動クランプと、このバグをエージェントに正しく直させる検証ステップ
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

▣ アプリ開発2026-09-29
Cloudflare をパージしても古い壁紙が届き続けた原因は、オリジン側で JPEG を握っていた XPageSpeed
同じ URL に上書きした壁紙画像が、Cloudflare をパージしても古いまま届き続けた運用の記録です。ローカル・オリジン・エッジの三者を突き合わせて層を名指しする検査、プレフィックスパージの使いどころ、Xserver の XPageSpeed を .htaccess で安全に切る書き方まで扱います。
▣ アプリ開発2026-09-19
見積書 PDF の自動化を一度にまとめて頼み、4 つに割り直すまで
受託の見積書を毎回コピーして作っていた手作業を、Antigravity に頼んで小さな PDF 出力ツールへ移した記録です。最初に全部をまとめて頼んで作り直すことになった理由と、データ・計算・見た目・保存の 4 つに割って渡し直した順番を、動くコードと一緒に書き残します。
▣ アプリ開発2026-09-03
musllinux ホイールが無い依存は、Alpine で失敗せずに遅くなります
Antigravity Python SDK の musllinux ホイール対応を機に、Alpine コンテナで C 拡張が純 Python 実装へ落ちる経路を実測しました。protobuf の直列化は 0.043ms から 36.2ms へ変わります。事前の棚卸しと検知の手順まで書き残します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます