---
title: Rails Favicon Generator
description: Rails serves favicons through Propshaft and the favicon_link_tag helper. Where files go under app/assets, and how to add apple-touch-icon and a manifest.
canonical: https://favicontools.com/platforms/rails-favicon
---

# Rails Favicon Generator

Rails expects the favicon to go through the asset pipeline. Put the files under app/assets/images and declare them with favicon_link_tag in the application layout so production fingerprinting keeps working.

## Asset pipeline, not public/ alone

Rails 8 defaults to Propshaft. Files under app/assets/images are fingerprinted on precompile and served from /assets/... in production. The favicon_link_tag helper resolves the logical name to that digested path, which is why a bare /favicon.ico in public/ and a helper-managed icon are different strategies.

public/favicon.ico still works as a legacy fallback for clients that request the root path without reading link tags. For the rest of the set (PNG sizes, apple-touch-icon, manifest) use the helpers in the layout so digests stay correct after each deploy.

## Where the files go

```
my-rails-app/
  app/
    assets/
      images/
        favicon.ico  <- add
        favicon-32x32.png  <- add
        apple-touch-icon.png  <- add  # 180x180
        icon-192.png  <- add
        icon-512.png  <- add
    views/
      layouts/
        application.html.erb  # helpers go here
  public/
    favicon.ico  <- add  # optional root fallback
    site.webmanifest  <- add
```

Propshaft copies everything under app/assets into public/assets on precompile. The layout should reference logical names, not the digested filenames.

## application.html.erb

```erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= content_for?(:title) ? yield(:title) : "My app" %></title>
    <meta name="viewport" content="width=device-width,initial-scale=1">

    <%= favicon_link_tag "favicon.ico" %>
    <%= favicon_link_tag "favicon-32x32.png", rel: "icon", type: "image/png", sizes: "32x32" %>
    <%= favicon_link_tag "apple-touch-icon.png", rel: "apple-touch-icon", type: "image/png" %>
    <link rel="manifest" href="/site.webmanifest">

    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
  </head>
  <body>
    <%= yield %>
  </body>
</html>
```

Pass type: and rel: for anything that is not a classic .ico. The helper defaults to rel=icon and type=image/x-icon, which is wrong for PNG and SVG.

> **Let the helper fingerprint the href:** Writing <link rel="icon" href="/assets/favicon.ico"> by hand skips the digest map. After the next assets:precompile the real file is favicon-<hash>.ico and the hardcoded tag 404s while favicon_link_tag keeps working.

## Check the small end first

- 16x16
- 32x32
- 48x48
- 96x96
- 180x180

Rendered at true pixel dimensions. A mark that survives 16px survives the tab; one that only reads at 180px will not.

## Rails favicon FAQ

### Propshaft or Sprockets: does the helper change?

favicon_link_tag is the same. Propshaft is the Rails 8 default and serves logical paths from app/assets without a Sprockets manifest. If you still run Sprockets, keep the files under app/assets/images and keep using the helper.

### Why put a copy in public/ as well?

Some clients request /favicon.ico before they parse link tags. A small root copy covers that case. The layout helpers still own the full set that modern browsers and iOS actually use.

### The icon did not update after deploy.

Confirm assets:precompile ran and the layout is using favicon_link_tag so the href changed with the digest. If you only replaced a file in public/ with the same name, browsers may keep the old cached icon until the URL changes or a private window is used.
