Create and manage favicons with Vite, Rollup, Webpack, Rspack, Nuxt, Vue CLI, Svelte, esbuild and Astro on top of itgalaxy/favicons
Daniel Bannert's open source work is supported by the community on GitHub Sponsors
npm install --dev-save @anolilab/unplugin-favicons favicons
yarn add -D @anolilab/unplugin-favicons favicons
pnpm add -D @anolilab/unplugin-favicons favicons
Add your base logo as logo.png
file to your assets folder.
unpluginFavicons({
/**
* Specify each icon type to render. Unlike `favicons`, this plugin is
* opt-in, meaning only the icon types you declare here will be rendered.
*
* For each icon type, all `favicons` options are supported. An
* additional `source` property is required to indicate the asset to be
* used for that icon type.
*/
icons: {
favicons: {
source: "./assets/favicon.png",
},
android: {
source: "./assets/android.png",
},
appleStartup: {
source: "./assets/apple-startup.png",
},
},
});
// vite.config.ts
import unpluginFavicons from "@anolilab/unplugin-favicons/vite";
export default defineConfig({
plugins: [
unpluginFavicons({
/* options */
}),
],
});
// rollup.config.js
import unpluginFavicons from "@anolilab/unplugin-favicons/rollup";
// To use the auto inject
import html from "@rollup/plugin-html";
export default {
plugins: [
// html(), // optional
unpluginFavicons({
/* options */
}),
],
};
// esbuild.config.js
import { build } from "esbuild";
build({
plugins: [
require("@anolilab/unplugin-favicons/esbuild")({
/* options */
}),
],
});
// webpack.config.js
module.exports = {
/* ... */
plugins: [
require("@anolilab/unplugin-favicons/webpack")({
/* options */
}),
],
};
// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
require("@anolilab/unplugin-favicons/webpack")({
/* options */
}),
],
},
};
Nuxt 2 and Nuxt Bridge
// nuxt.config.js
export default {
buildModules: [
[
"@anolilab/unplugin-favicons/nuxt",
{
/* options */
},
],
],
};
Nuxt 3
// nuxt.config.js
export default defineNuxtConfig({
modules: [
[
"@anolilab/unplugin-favicons/nuxt",
{
/* options */
},
],
],
});
See the Nuxt example for a working example project.
The @anolilab/unplugin-favicons
plugin should be configured in the vite.config.js
configuration file:
// vite.config.js
import { defineConfig } from "vite";
import { sveltekit } from "@sveltejs/kit/vite";
import unpluginFavicons from "@anolilab/unplugin-favicons/vite";
export default defineConfig({
plugins: [
sveltekit(),
unpluginFavicons({
/* options */
}),
],
});
Then add src/hooks.server.ts
to rewrite the head tag with hooks
:
import { metadata } from "@anolilab/unplugin-favicons/runtime"; // use default import
import type { Handle } from "@sveltejs/kit";
export const handle: Handle = async ({ event, resolve }) => {
const response = await resolve(event, {
transformPageChunk: ({ html }) => html.replace("</head>", `${metadata}</head>`),
});
return response;
};
Check instructions in the Frameworks -> Svelte
section below if you faced module import errors.
See the SvelteKit example for a working example project.
Svelte support requires the @sveltejs/vite-plugin-svelte
plugin:
npm i -D @sveltejs/vite-plugin-svelte
The @anolilab/unplugin-favicons
plugin should be configured in the vite.config.js
configuration file:
// vite.config.js
import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import unpluginFavicons from "@anolilab/unplugin-favicons/vite";
export default defineConfig({
plugins: [
svelte(),
unpluginFavicons({
/* options */
}),
],
});
Check instructions in the Frameworks -> Svelte
section below if you faced module import errors.
See the Svelte + Vite example for a working example project.
The @anolilab/unplugin-favicons
plugin should be configured on next.config.js
configuration file:
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
webpack(config) {
config.plugins.push(
require("@anolilab/unplugin-favicons/webpack")({
/* options */
}),
);
return config;
},
};
Check instructions in the Frameworks -> React
section below if you faced module import errors.
See the Next.js example for a working example project.
// astro.config.mjs
import { defineConfig } from "astro/config";
import unpluginFavicons from "@anolilab/unplugin-favicons/vite";
// https://astro.build/config
export default defineConfig({
vite: {
plugins: [
unpluginFavicons({
/* options */
}),
],
},
});
See the Astro example for a working example project.
The default configuration will automatically generate webapp manifest files along with 44 different icon formats as appropriate for iOS devices, Android devices, Windows Phone and various desktop browsers out of your single logo.png
.
Tip: You might want to fine tune what vendors to support.
Under the hood, Vite/Rollup resolve the paths to the logo and favicons according to the following rules:
If /path/to/logo
is absolute, there is nothing to resolve and the path
specified is used as is.
If ./path/to/logo
is relative, it’s resolved with respect to process.cwd()
.
In combination with Vite’s html plugin hooks it will also inject the necessary html for you:
<link rel="apple-touch-icon" sizes="57x57" href="/assets/apple-touch-icon-57x57.png" />
<link rel="apple-touch-icon" sizes="60x60" href="/assets/apple-touch-icon-60x60.png" />
<link rel="apple-touch-icon" sizes="72x72" href="/assets/apple-touch-icon-72x72.png" />
<link rel="apple-touch-icon" sizes="76x76" href="/assets/apple-touch-icon-76x76.png" />
<link rel="apple-touch-icon" sizes="114x114" href="/assets/apple-touch-icon-114x114.png" />
<link rel="apple-touch-icon" sizes="120x120" href="/assets/apple-touch-icon-120x120.png" />
<link rel="apple-touch-icon" sizes="144x144" href="/assets/apple-touch-icon-144x144.png" />
<link rel="apple-touch-icon" sizes="152x152" href="/assets/apple-touch-icon-152x152.png" />
<link rel="apple-touch-icon" sizes="167x167" href="/assets/apple-touch-icon-167x167.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon-180x180.png" />
<link rel="apple-touch-icon" sizes="1024x1024" href="/assets/apple-touch-icon-1024x1024.png" />
<link
rel="apple-touch-startup-image"
media="(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 1)"
href="/assets/apple-touch-startup-image-320x460.png"
/>
<link
rel="apple-touch-startup-image"
media="(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 2)"
href="/assets/apple-touch-startup-image-640x920.png"
/>
<link
rel="apple-touch-startup-image"
media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)"
href="/assets/apple-touch-startup-image-640x1096.png"
/>
<link
rel="apple-touch-startup-image"
media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)"
href="/assets/apple-touch-startup-image-750x1294.png"
/>
<link
rel="apple-touch-startup-image"
media="(device-width: 414px) and (device-height: 736px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 3)"
href="/assets/apple-touch-startup-image-1182x2208.png"
/>
<link
rel="apple-touch-startup-image"
media="(device-width: 414px) and (device-height: 736px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 3)"
href="/assets/apple-touch-startup-image-1242x2148.png"
/>
<link
rel="apple-touch-startup-image"
media="(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 1)"
href="/assets/apple-touch-startup-image-748x1024.png"
/>
<link
rel="apple-touch-startup-image"
media="(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)"
href="/assets/apple-touch-startup-image-1496x2048.png"
/>
<link
rel="apple-touch-startup-image"
media="(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 1)"
href="/assets/apple-touch-startup-image-768x1004.png"
/>
<link
rel="apple-touch-startup-image"
media="(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)"
href="/assets/apple-touch-startup-image-1536x2008.png"
/>
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16x16.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="228x228" href="/assets/coast-228x228.png" />
<link rel="manifest" href="/assets/manifest.json" />
<link rel="shortcut icon" href="/assets/favicon.ico" />
<link rel="yandex-tableau-widget" href="/assets/yandex-browser-manifest.json" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" />
<meta name="application-name" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="msapplication-TileColor" content="#fff" />
<meta name="msapplication-TileImage" content="/assets/mstile-144x144.png" />
<meta name="msapplication-config" content="/assets/browserconfig.xml" />
<meta name="theme-color" content="#fff" />
unpluginFavicons({
/** Your source logo (Will default to ) */
logo?: "assets/logo.png",
/** Inject html links/metadata. */
inject?: true,
/** `Favicons` configuration options
* - [See `favicons` documentation](https://github.com/itgalaxy/favicons) */
favicons?: FaviconsConfig,
/** The root of the project from which you want to load metadata */
projectRoot?: process.cwd(),
})
To fine tune what icons/metadata is generated, refer to favicons’ documentation.
The options specified under favicons:
are handed over as is to [favicons],
except that if appName
, appDescription
, version
, developerName
or
developerURL
are left undefined
, they will be automatically inferred
respectively from name
, description
, version
, author.name
and
author.url
as defined in the nearest package.json
if available.
And if there’s no author
it will use the first in the contributors
.
To disable automatically retrieving metadata from package.json
, set
to null
the properties you want to omit.
unpluginFavicons({
logo: "./src/logo.png", // svg works too!
favicons: {
appName: "my-app",
appDescription: "My awesome App",
developerName: "Me",
developerURL: null, // prevent retrieving from the nearest package.json
background: "#ddd",
theme_color: "#333",
icons: {
coast: false,
yandex: false,
},
},
});
To fine tune what icons/metadata is generated, refer to favicons’ documentation.
Vite calls the HTML transform hook for each HTML file template file you have configured in Vite, so this works automatically.
The @anolilab/unplugin-favicons
plugin also exports a runtime module that can be used to inject the generated metadata into your HTML files or access the files
and images
used in the metadata.
import { metadata, images, files } from "@anolilab/unplugin-favicons/runtime";
console.log(metadata, images, files);
Take a look at the CHANGELOG.md.
You’re free to contribute to this project by submitting issues and/or pull requests.
Please keep in mind that every change and feature should be covered by tests.
This project is licensed under MIT.
Libraries in this ecosystem make the best effort to track Node.js’ release schedule. Here’s a post on why we think this is important.
If you would like to help take a look at the list of issues and check our Contributing guild.
Note: please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
The anolilab vite-plugin-favicon is open-sourced software licensed under the MIT license