静的サイトジェネレーター(SSG)でサイトを公開したのに、ブラウザのタブに何もない白い四角が表示されてがっかりした経験はありませんか?Astro、Next.js、Gatsby といった SSG は、従来の WordPress テーマとは全く異なるアセットの扱い方をします。そのため、静的サイトジェネレーター向けの favicon を設定する際に混乱することがよくあります。画像ファイルは用意していても、ビルドプロセスがそれを削除してしまったり、パスが間違っていたり、キャッシュが古いアイコンを頑なに保持していたりすることがあるのです。

開発者体験で定評のある Stripe などは、単にロゴをルートフォルダに放り込んで「うまくいくことを祈る」ようなことはしません。彼らは構造化されたアプローチを採用し、アイコンが瞬時に読み込まれ、あらゆるデバイスで完璧にスケーリングされるようにしています。私たちも同じことができます。重要なのは画像を持っていることだけでなく、特定の SSG が静的アセットやメタデータをどう扱うかを理解することにあります。

核心となる問題:ビルドツールとブラウザの認識違い

多くの開発者が犯すミスは、SSG を従来の CMS のように扱うことです。WordPress では画像をアップロードすれば魔法のように表示されますが、2026 年現在、Next.js や Astro といったモダンなフレームワークでは、ビルドシステムに対してアイコンの場所を明示的に指示する必要があります。favicon.ico を誤ったディレクトリに配置すると、ビルドツールがそれを完全に無視するか、最悪の場合、404 エラーにつながる壊れたリンクを生成してしまいます。

そのため、我々は「関心の分離」を厳格に行うことを推奨します。ソースコードは src 配下に置き、公開用のアセットはフレームワークに応じて public または static フォルダに配置します。しかし、単にファイルをそこに置くだけでは、SVG、Apple Touch Icon、manifest ファイルなどを同時に期待する現代のブラウザには対応できません。

ステップ 1:アイコンアセットの準備

設定ファイルに触れる前に、必要なファイルを用意しましょう。ロゴを単にリサイズするだけでは不十分です。512x512 の PNG は、16x16 のブラウザタブには役に立ちません。多形式のスタックが必要です。Mzu favicondl を使って完全なセットを生成しましょう:現代のブラウザ向けの SVG、フォールバック用の PNG、そしてレガシーサポート用の ICO です。

public フォルダ内は以下のように整理してください:

SVG を省略するのは間違いです。ダークモード対応や高 DPI スクリーンでの鮮明なレンダリングが可能になるため、2026 年においては必須条件です。

ステップ 2:静的サイトジェネレーターの設定

ここからはフレームワーク固有のロジックに入ります。多くのチュートリアルが失敗するのは、一般化しすぎているためです。最も一般的な 2 つのシナリオを見てみましょう。

Astro と Next.js(App Router)の場合:
これらのフレームワークはファイルベースのルーティングとメタデータ管理へ移行しています。複雑なプラグインはもう不要です。public ディレクトリに favicon.ico と favicon.svg を置くだけで、フレームワークが自動的にルートで配信します。site.webmanifest については、レイアウトファイル内の href が /site.webmanifest を指していることを確認してください。

Gatsby と Nuxt の場合:
これらのアーキテクチャでは、多くの場合プラグインが必要です。Gatsby では、gatsby-config.js で gatsby-plugin-manifest を使用する必要があります。これをスキップすると、PWA アイコンが登録されず、汎用的なブラウザアイコンが表示されてしまいます。

// Gatsby サイト向けの gatsby-config.js の例
module.exports = {
  plugins: [
    {
      resolve: 'gatsby-plugin-manifest',
      options: {
        name: 'Your Site Name',
        short_name: 'YourSite',
        start_url: '/',
        background_color: '#ffffff',
        theme_color: '#000000',
        display: 'standalone',
        icon: 'src/images/icon.png', // 生成元の画像
      },
    },
  ],
};

注目すべきは、src 内のソース画像を指定し、プラグインにリサイズを任せている点です。これが Gatsby において最も安全な方法です。

ステップ 3:HTML タグの正しい注入

ファイルを配置しても、ブラウザに何をロードすべきかを指示する必要があります。ブラウザが /favicon.ico を推測することに任せてはいけません。明示的に記述しましょう。メインのレイアウトファイル(多くの場合 layout.tsx や BaseHead.astro)にリンクタグを追加します。

以下が、コピー&ペーストして使えるモダンなスタックです:

<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/png" href="/favicon.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />

順序は重要です。ブラウザは上から下へ読み込みます。PNG を先に記述すると、SVG が無視されてしまう可能性があります。スケーラビリティとダークモード対応の観点から、常に SVG を最優先してください。

アイコンを壊す一般的な落とし穴

正しい設定を行っても、問題は発生します。最も頻繁な問題はキャッシュです。静的サイトは定義上「静的」です。favicon を変更してもキャッシュをクリアしなければ、ユーザーは数週間も古いアイコンを見続けることになります。そのため、manifest にバージョンクエリ文字列を付与するか、ビルド時にハッシュ値を使用することを常に推奨しています。

もう一つの罠は、コンソールに表示される 404 エラーです。ブラウザが /favicon.ico をリクエストしているのに、/favicon.svg しかない場合、ログにノイズが表示されます。致命的ではありませんが、プロフェッショナルな印象を与えません。クリーンなコンソールを維持したい場合は、少なくとも .ico のフォールバックを用意してください。

最後に、robots.txt を確認してください。一部の過剰な SEO プラグインは、favicon を含む画像ファイルへのアクセスをブロックすることがあります。Google Search Console でアイコンが表示されない場合は、robots.txt が誤って /favicon.ico パスを禁止していないか確認しましょう。

このアプローチが勝つ理由

アセットの生成とビルドロジックを分離することで、柔軟性が得られます。サイト全体を再ビルドすることなく、SVG をダークモード用のバリエーションに差し替えることができます。HTML に触れることなく manifest を更新することも可能です。これが、静的サイトジェネレーター向けの favicon を扱うプロフェッショナルな方法です。

サイトをテンプレートのまま放置しないでください。アセットを自分で制御しましょう。手元のロゴから完璧なアイコンセットを生成する必要がある場合は、リサイズや形式変換という重労働を Mzu favicondl に任せてください。その後、上記の手順でそのファイルを SSG に組み込むだけです。ユーザーはすぐにその違いに気づくはずです。