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

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.

Starting a Metalsmith Project

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.