Adding a Favicon in Metalsmith

Christian Emmer
Christian Emmer
Feb 17, 2020 · 3 min read

Favicons are low-resolution website icons that web browsers use to help identify bookmarks, tabs, and desktop icons at a glance - and they're easy to add in Metalsmith.

Project setup

To keep this article short and to the point we're not going to set up a full website, just enough to show sample usage. See "Starting a Metalsmith Project" for a more complete article on how to set up a Metalsmith project.

Starting a Metalsmith Project
Starting a Metalsmith Project
Sep 19, 2019 · 12 min read

Metalsmith is a plugin-based static site generator originally from Segment. It's a current favorite of mine because of how sites are built as a pipeline of plugins where the output of each plugin is the input of the next. This allows for strong control over what happens and when it happens.

Installing packages

Starting with an empty project, install some Metalsmith packages:

npm install --save metalsmith metalsmith-favicons metalsmith-layouts jstransformer-handlebars

Source file structure

Create the following directories and files for use in the build pipeline:

├── index.js
├── layouts
│   └── page.hbs
└── src
    ├── favicon.png
    └── index.html

Any valid PNG file will do for src/favicon.png, so use a logo of yours or another website's.

Then fill in your src/page.hbs like this:

<!DOCTYPE html>
    {{#each favicons.html}}
        {{{ this }}}
    {{{ contents }}}

Which will serve as a base template for us to be able to use the favicons metadata.

You can fill src/index.html in with any content such as lorem ipsum, it isn't important for the point of this article.

Writing the source files

Set up your index.js file like this:

const Metalsmith = require('metalsmith');
const favicons   = require('metalsmith-favicons');
const layouts    = require('metalsmith-layouts');

// Define some site-wide metadata
const siteName = 'Your Webiste Name';
const siteDescription = 'Your website description.';
const siteURL = '';

    .source('./src')         // source directory for the pipeline
    .use(favicons({          // generate icon files
        src: 'favicon.png',
        dest: '.',
        appName: siteName,
        appDescription: siteDescription,
        developerName: siteName,
        developerURL: siteURL,
        start_url: siteURL,
        icons: {
            android: true,
            appleIcon: true,
            favicons: true,
            windows: true
    .use(layouts({           // use Handlebars templating
        pattern: '**/*.html',
        default: 'page.hbs',
        engine: 'handlebars'
    .destination('./build')  // destination directory of the pipeline
    .clean(true)             // clean the destination directory before build
    .build(function (err) {  // execute the build
        if (err) {
            throw err;

This will:

  • Generate a build/manifest.json web app manifest .
  • Generate build/android-chrome-*.png icons to be used in build/manifest.json.
  • Generate build/apple-touch*.png icons to be used in <link rel="apple-touch-icon">s.
  • Generate build/favicon.* icons to be used in <link rel="icon">s.
  • Generate a build/browserconfig.xml browser configuration schema reference .
  • Generate build/mstile-*.png icons to be used in build/browserconfig.xml.
  • Process src/index.html through layouts/page.hbs, adding the icon metadata to the page.

Note this does a lot more than just generate a single favicon.ico or favicon.png, it also generates a number of non-image files used for defining "web apps" or "pinned sites." See the RealFaviconGenerator FAQ for a great explanation of each of the files generated.


Run the build command like normal:

node index

Then open the resulting build/index.html in your browser, and you should the favicon displayed.