Fashionable Favicons

Fashionable Favicons

How this website fetches favicons statically and automagically.

29.02.2024

Why? 🤔

If you have spent more than a minute on this website, you'll know that I like putting icons and emojis in text. 📝 They make everything more fun and serve as a visual aid to quickly identify links and topics. 🧠

Now, I could go and manually download and resize every single favicon I want to use, but that would be a lot of work. 💩 Instead, I fetch them dynamically at build time, convert them to .webp and serve them statically.

Look at them go! 🚀

Facebook

Favicon
  Twitter
Favicon
  Instagram
Favicon
  LinkedIn
Favicon
  GitHub
Favicon
  Minecraft
Favicon
  Reddit
Favicon
  YouTube
Favicon
  Spotify
Favicon
  Discord
Favicon
  Twitch
Favicon
  WhatsApp
Favicon
  Slack
Favicon
  Google
Favicon
  Apple
Favicon
  xkcd
Favicon

The easy way 🥲

Having favicons show up next to links could be soo easy:

<a href="https://kosro.de">
  Click me
  <img src="http://www.google.com/s2/favicons?domain=kosro.de" />
</a>

This works thanks to Google's internal favicon API. There's also some other services that offer this, like DuckDuckGo and Yandex:

https://www.google.com/s2/favicons?domain=kosro.de?sz=64

https://icons.duckduckgo.com/ip2/kosro.de.ico

https://favicon.yandex.net/favicon/v2/kosro.de/reddit.com

Keep in mind that these services are not officially documented and could be taken down at any time.

GDPR Compliance 🇪🇺

The GDPR

Favicon
basically (and rightly 😈) regards the USA as a third world country, thanks to it's horrid privacy laws.

As IP addresses are considered personal data, explicit consent is required before any requests may be made to a server in the USA.

This means that directly using most favicon APIs is a no-go for any website that wants to be GDPR compliant. Shucks. 💩

The hard way 🪨

Luckily, Nuxt Image

Favicon
has a solution for this. It's a module that allows you to fetch images statically at build time. This means that the images are already on the server when the user requests the page, and no further external requests are made.

Awesome! So I can just use the Google API and be done with it, right?

Nope.

Turns out, Nuxt Image

Favicon
and IPX
Favicon
completely shit themselves as soon as there's query parameters in the image URL.

WHICH IS MENTIONED EXACTLY 0 TIMES IN THE DOCS 🤬

At least there's this issue

Favicon
...

Unfortunately, most favicon APIs require query parameters to pass the URL or desired size. DuckDuckGo

Favicon
does not, but it returns some icons in .ico format, which IPX
Favicon
can't handle. This is why I had to resort to fetching favicons from Yandex
Favicon
.

Making it pretty ✨

So far so good. Next problem:

Some icons are black. The website's background is black.

Enter fast-average-color

Favicon
, a module capable of extracting the average color of an image element, efficiently and client side.

I register a callback for when the icon is loaded (or mounted in case of prerendered pages

Favicon
), get it's average color and calculate the saturation. If both brightness and saturation are low, I invert the icon's colors.

And that's it!