Adding Favicon and Manifest Files to a Phoenix app
Note: This guide is based on Phoenix 1.7
You have a brand new Phoenix app in the works and have some favicon assets ready. For example, uploading an image to a service like Favicon Generator will get you a handful of files:
- android-chrome-192x192.png
- android-chrome-512x512.png
- apple-touch-icon.png
- favicon-16x16.png
- favicon-32x32.png
- favicon.ico
- site.webmanifest (I rename this to manifest.json)
Next you plop them into your_app/priv/static/
and add links into your_app/lib/your_app_web/components/layouts/root.html.heex
.
<!DOCTYPE html>
<html lang="en">
<head>
...
<link rel="apple-touch-icon" sizes="180x180" href={~p"/apple-touch-icon.png"} />
<link rel="icon" type="image/png" sizes="32x32" href={~p"/favicon-32x32.png"} />
<link rel="icon" type="image/png" sizes="16x16" href={~p"/favicon-16x16.png"} />
<link rel="manifest" href={~p"/manifest.json"} />
</head>
<body>
<%= @inner_content %>
</body>
</html>
But then you immediately get hit with errors. First, trying to GET a resource /favicon-32x32.png
will give you a router error that there is no GET route defined:
[debug] ** (Phoenix.Router.NoRouteError) no route found for GET /favicon-32x32.png (YourAppWeb.Router)
Second, the compiler will give you a warning too:
warning: no route path for YourAppWeb.Router matches "/favicon-32x32.png"
That compiler warning comes curtesy of the new verified routes sigil ~p"/favicon-32x32.png"
, which checks the validity of routes at compile time.
Ok, so recall that when a request hits a Phoenix endpoint, it passes through a pipeline of Plugs. If you open up lib/your_app_web/endpoint.ex
, you can see the Plug that handles static assets:
...
# Serve at "/" the static files from "priv/static" directory.
#
# You should set gzip to true if you are running phx.digest
# when deploying your static files in production.
plug Plug.Static,
at: "/",
from: :personal,
gzip: false,
only: PersonalWeb.static_paths()
...
In your IDE, highlight static_paths()
and go to the implementation. That will open up lib/your_app_web.ex
.
def static_paths, do: ~w(assets fonts images favicon.ico robots.txt)
Add the new assets to the static_paths
function.
def static_paths, do: ~w(assets fonts images favicon.ico robots.txt manifest.json apple-touch-icon.png favicon-32x32.png favicon-16x16.png)
That’s all there is to it!