BartOtten
Feature Request: LiveView Dynamic Favicon
Proposal
- Support DOM patching of the HTML link element for a favicon.
- Add the special @page_favicon assign mimicking the @page_title assign so each page can have it’s own dynamic favicon; supporting multiple tabs for an application with different ‘statuses’.
Reason
Many modern web applications have dynamic favicons. These dynamic favicons are used to notify browser users of events or statuses. For example: unread messages or a CI build status. As those use cases are quite common, providing such functionality seems to fit the ‘no Javascript’-philosophy. Additionaly it seems to align with the automagic @page_title.
Because the root layout from the Plug pipeline is rendered outside of LiveView, the contents cannot be dynamically changed. The one exception is the
<title>of the HTML document. Phoenix LiveView special cases the@page_titleassign to allow dynamically updating the title of the page, which is useful when using live navigation, or annotating the browser tab with a notification. For example, to update the user’s notification count in the browser’s title bar, first set thepage_titleassign on mount
Live layouts — Phoenix LiveView v1.2.5
Current State
- The HTML
linkelement for favicons is placed inlayout/root_live.html.heex. No native logic is in place to update it in the DOM and there is no @page_favicon. - The HTML
titleelement is placed in `layout/root_live.html.heex. Native logic is in place to update the element in the DOM when the @page_title assignment is changed.
Todo
- get approval for feature
- research possibilities
- draft design
- get approval for design
- implement
I am willing to work on this as contribution to the community.
Links
[LiveView Dynamic Favicon?]
[https://medium.com/@alperen.talaslioglu/building-dynamic-favicon-with-javascript-223ad7999661]
Most Liked
AndyL
Here’s some rough design ideas:
Let there be a special assign @favicon_href
The live_favicon_tag would go into layout/root_live.html.heex
<%= live_favicon_tag assigns[:favicon_href] || "/images/favicon.ico" %>
The live_favicon_tag function would emit the following HTML
<link id="phx-favicon" rel="icon" type="image/x-icon" href="/images/favicon.ico"/>
Add an event listener to the client javascript
window.addEventListener("phx:change-favicon", (e) => {
var href = e.detail.href
var fabtag = document.getElementById('phx-favicon')
fabtag.href = href
})
On the server, when the LiveView process detects that @favicon_href has changed, push an event to the client:
push_event(socket, "change-favicon", %{href: @favicon_href})}
With this approach, add-on packages (like live_dashboard) could add their own favicon images to priv/images, and then use their own favicons in their particular LiveViews.
BartOtten
It’s gonna be 3 I guess.
Took some time to explore the problem domain a little further. As a result, I will create multiple libs all targeted at manipulating the static head.
Phoenix Live Head
Low level lib which includes functions to manipulate the head of the page incl. generic Javascript. It also takes care of minimizing data over the wire. The other libs depend on it, direct usage will be discouraged.
Phoenix Live Favicon
Lib which supports dynamic favicons! It will include a helper function to cover some exotic use cases, but will mainly be used with the HTML link element(s).
Phoenix Live Metadata
This one is a convenience lib which can be used pre-production (on production it is harmful!). It updates the metadata in the head for easy inspection.
Phoenix Live -other head element-
—-
This way devs can pick the parts they need for each environment.
BartOtten
Just to keep everyone informed
To be super clear
I fully understand and respect Chris’ rejection. He just doesn’t want anyone spilling time so he was quick to respond.
The rejection
The rejection was based on the commit and example code published.
The PR did not yet include support for multi favicon links nor some other features, as it was not final code yet. I used a ‘draft PR’ which GitHub says “is meant for discussion, not review” just to make sure the ‘we are working on this idea already’ would be represented at GitHub too and discussion about code could take place there.
So Chris was right the published code at that time could be done with 10 lines of primitives and -based on that- changing Phoenix codebase should not happen.
Future
Currently I see 4 options.
- Write a blog post how it’s done with primitives
- Write a helper lib/files requiring manual changes in Javascript files.
- Write a lib which solely relies on Phoenix so it’s a ‘add to mix dep’ and go.
- Challenge the rejection with the improved ‘include in Phoenix Liveview’ code and description why Chris’ solution won’t work (enough)
When option 3 is viable, it’s probably gonna be 3.
While the code for 4 is ready for a challenge, the challenge won’t happen until the pro’s and cons of all the options are clear and comparable.
So far
So far I have the code for 2 and 4 (they share most lines). Will make an attempt at 3 this weekend, should be quite straight forward.
One way or another we will have dynamic multi-link favicons in our Phoenix Live View apps; so just subscribe to this topic, wait and relax ![]()
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








