If you've ever checked your production logs and found them choked with ActionController::RoutingError (No route matches [GET] '/favicon.ico') errors, your ruby on rails favicon setup is leaking. Browsers are aggressively stubborn. They will hunt for that exact file path at the root of your domain on every single visit, regardless of what your HTML header actually dictates.

Look at GitHub, arguably the most famous Rails application in existence. They use dynamic SVG icons to show notification badges in the browser tab. Yet, if you inspect their network traffic, they still keep a hardcoded .ico file at their domain root. They do this simply to satisfy dumb web crawlers and legacy browsers that ignore modern HTML tags.

The Rails community often argues over whether to put icons in the public folder or run them through the asset pipeline. My stance? You must do both. Relying solely on Rails view helpers leaves you vulnerable to bot traffic 404s. Relying solely on the static public folder robs you of cache-busting fingerprints when you rebrand. We need a hybrid approach.

The Hybrid Ruby on Rails Favicon Strategy

Setting this up correctly requires splitting your assets. We will feed the legacy bots exactly what they want, while serving modern, cache-busted assets to real users.

Step 1: Silence the Root Requests

First, grab your base favicon.ico file. If you don't have one, generate it using Mzu favicondl. Drop this file directly into your Rails public/ directory. Do not put it in app/assets.

The public folder is served directly by Puma (or Nginx/Caddy if you're behind a reverse proxy) without ever hitting the Rails router. This instantly stops the routing errors. It acts as a silent fallback for tools like RSS readers or ancient versions of Internet Explorer.

Step 2: Asset Pipeline Integration

Next, we handle the modern web. You need an SVG for modern browsers and an Apple Touch Icon for iOS devices. These belong in app/assets/images/.

Why? Because Rails (whether you use Propshaft or legacy Sprockets in 2026) will append a unique hash to the filename during asset precompilation. When your marketing team decides to tweak the logo's background color, the compiled filename changes (e.g., icon-a1b2c3d4.svg). This instantly busts the browser cache, ensuring returning users see the new logo immediately.

Step 3: Writing the ERB Helpers

Open your app/views/layouts/application.html.erb file. Rails provides a built-in favicon_link_tag helper, but we need to configure it explicitly to prevent it from making incorrect assumptions about file types.

<head>
  <!-- Base fallback for browsers that ignore the public folder -->
  <%= favicon_link_tag 'favicon.ico' %>

  <!-- Modern SVG with dark mode support -->
  <%= favicon_link_tag 'icon.svg', rel: 'icon', type: 'image/svg+xml' %>

  <!-- Apple Touch Icon for iOS home screens -->
  <%= favicon_link_tag 'apple-touch-icon.png', rel: 'apple-touch-icon', type: 'image/png' %>
</head>

Notice we explicitly define the rel and type attributes for the modern formats. If you omit these, Rails defaults to rel='icon' type='image/x-icon', which actually breaks SVG rendering in strict browsers like Chrome.

Step 4: Handling Web App Manifests in Rails

If you are building a Progressive Web App (PWA), you need a manifest.json file. The problem? A static JSON file in the public folder cannot reference your fingerprinted asset pipeline images.

The solution is to route your manifest through Rails. Create a file at app/views/pwa/manifest.json.erb (or wherever your PWA controller lives) and use the image_path helper:

{
  "name": "My Rails App",
  "icons": [
    {
      "src": "<%= image_path('icon-512.png') %>",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

This ensures your Android users always get the correct, cache-busted icon when installing your app to their home screen.

Common Production Pitfalls

Setting this up locally usually takes five minutes, but debugging a broken deployment can take hours. Here is what usually goes wrong when you push to production.

Getting your ruby on rails favicon right is about understanding the balance between static files and compiled assets. Put the legacy file in the root, let the asset pipeline handle the modern formats, and use the built-in helpers to tie it all together. If you are tired of seeing favicon 404 errors in your logs, this hybrid approach fixes it permanently. Need to generate the exact sizes for your app/assets folder? Check out our Apple Touch Icon sizes guide to avoid bloating your repository.