How to easily generate favicons

#it #javascript #11ty

Recently I switched from Gatsby to 11ty. There is a Gatsby plugin to generate favicons automatically. I wanted to have something similar for my new blog.

I realized that I don't want to generate favicons on every build. It does not make sense. I have had the same favicon for 3 years or more.

I found an excellent package called... favicons. It can generate favicons for all platforms, manifest files and even the HTML meta tags.

Initially, I thought to create an 11ty plugin to be rich and famous, but I chose not to. Why? It's too simple and I don't see a point to have it as a plugin.

Let's generate favicons.

npm install favicons --save

The script requires three variables:

  • a path to an image from which we want to generate favicons
  • a path to a directory where we want to store all files
  • a path to a directory where we want to save the HTML meta tags

The script is straightforward. I keep it inside _scripts directory.

const fs = require("fs");
const favicons = require("favicons");

const source = "content/images/eshlox.jpg";
const faviconsPath = "_assets/favicons/";
const faviconsHtmlPath = "_layouts/_favicons.njk";

const configuration = {
path: "/assets/favicons",
appName: "eshlox.net",
appShortName: null,
appDescription: null,
developerName: "eshlox",
developerURL: "https://eshlox.net",
dir: "auto",
lang: "en-US",
background: "#fafafa",
theme_color: "#111111",
appleStatusBarStyle: "black-translucent",
display: "standalone",
orientation: "any",
scope: "/",
start_url: "/",
version: "1.0",
logging: false,
pixel_art: false,
loadManifestWithCredentials: false,
icons: {
android: true,
appleIcon: false,
appleStartup: false,
coast: false,
favicons: true,
firefox: false,
windows: false,
yandex: true,
},
};

const callback = function (error, response) {
if (error) {
console.log(error.message);
return;
}

if (!fs.existsSync(faviconsPath)) {
fs.mkdirSync(faviconsPath);
}

response.images.forEach((element) => {
fs.writeFileSync(`${faviconsPath}/${element.name}`, element.contents);
});

response.files.forEach((element) => {
fs.writeFileSync(`${faviconsPath}/${element.name}`, element.contents);
});

fs.writeFileSync(faviconsHtmlPath, response.html.join("\n"));
};

favicons(source, configuration, callback);

You can find the full documentation on Github so update the configuration to your needs. The script uses the favicons library, which does all the work and then creates a directory, saves all the images, all the files and the HTML in the given paths.

Every time I want to generate or update favicons, I have to run a single command and commit all the files to the repository.

node _scripts/generate_favicons.js

The _assets/favicons directory content:

tree _assets/favicons

_assets/favicons
├── android-chrome-144x144.png
├── android-chrome-192x192.png
├── android-chrome-256x256.png
├── android-chrome-36x36.png
├── android-chrome-384x384.png
├── android-chrome-48x48.png
├── android-chrome-512x512.png
├── android-chrome-72x72.png
├── android-chrome-96x96.png
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon-48x48.png
├── favicon.ico
├── manifest.json
├── yandex-browser-50x50.png
└── yandex-browser-manifest.json

0 directories, 16 files

The _layouts/_favicons.njk file content:

<link rel="shortcut icon" href="/assets/favicons/favicon.ico" />
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/assets/favicons/favicon-16x16.png"
/>

<link
rel="icon"
type="image/png"
sizes="32x32"
href="/assets/favicons/favicon-32x32.png"
/>

<link
rel="icon"
type="image/png"
sizes="48x48"
href="/assets/favicons/favicon-48x48.png"
/>

<link rel="manifest" href="/assets/favicons/manifest.json" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="theme-color" content="#111111" />
<meta name="application-name" content="eshlox.net" />
<link
rel="yandex-tableau-widget"
href="/assets/favicons/yandex-browser-manifest.json"
/>

That's all I need. I can easily include the _layouts/_favicons.njk file in my _layouts/base.njk to add favicons to all pages.

{% include "./_favicons.njk" %}

You can see the result on this blog.