Skip to content

Latest commit

 

History

History
424 lines (310 loc) · 11.9 KB

File metadata and controls

424 lines (310 loc) · 11.9 KB

@profullstack/favicon-generator

Generate PNG icons from an SVG or PNG source for iOS and PWA compatibility. A modern, flexible Node.js tool that converts your source logo into all the icon sizes you need for mobile devices and progressive web apps.

npm version License: MIT

Features

  • 🎨 Convert SVG or PNG source art to multiple PNG icon sizes
  • 🖼️ PNG sources for when you only have raster logo art
  • 📱 iOS Apple Touch Icon support
  • 🌐 PWA icon generation
  • 🖼️ Automatic favicon size generation (16x16, 32x32)
  • ⚙️ Configurable quality and compression
  • 🎯 CLI with interactive mode
  • 📦 ESM module for programmatic use
  • ✅ Comprehensive test coverage
  • 🚀 Built with modern Node.js (v20+)

Installation

# Using pnpm (recommended)
pnpm add @profullstack/favicon-generator

# Using npm
npm install @profullstack/favicon-generator

# Using yarn
yarn add @profullstack/favicon-generator

Global Installation (for CLI)

# Using pnpm
pnpm add -g @profullstack/favicon-generator

# Using npm
npm install -g @profullstack/favicon-generator

Usage

CLI Usage

Interactive Mode

Simply run the command without arguments to enter interactive mode:

fav

You'll be prompted for:

  • Source file path (.svg or .png)
  • Output directory
  • PNG quality (1-100)
  • Compression level (0-9)
  • Whether to generate additional favicon sizes

Command Line Arguments

# Basic usage with an SVG source
fav -i favicon.svg -o ./icons

# Basic usage with a PNG source
fav -i logo.png -o ./icons

# With custom quality and compression
fav -i logo.svg -o ./public/icons -q 90 -c 7

# Silent mode (no output)
fav -i favicon.svg -o ./icons --silent

# Skip favicon generation
fav -i favicon.svg -o ./icons --no-favicon

# Show help
fav --help

# Show version
fav --version

CLI Options

Option Alias Description Default
--input -i Path to source .svg or .png ./favicon.svg
--output -o Output directory ./icons
--quality -q PNG quality (1-100) 95
--compression -c Compression level (0-9) 9
--no-favicon Skip additional favicon sizes false
--silent Suppress output messages false
--help -h Show help message
--version -v Show version number

Programmatic Usage (ESM)

Basic Example

import { generateIcons } from '@profullstack/favicon-generator';

const results = await generateIcons({
  inputPath: './favicon.svg', // or './logo.png'
  outputDir: './icons',
});

console.log(`Generated ${results.icons.length} icons`);

PNG Source Example

import { generateIcons } from '@profullstack/favicon-generator';

const results = await generateIcons({
  inputPath: './logo.png',
  outputDir: './public/icons',
});

// 'png' for a raster source, 'svg' for a vector one
console.log(results.inputFormat); // 'png'

// A PNG source has no vector equivalent, so no favicon.svg is written
console.log(results.rootFavicons); // { png: ..., ico: ... }

Custom Configuration

import { generateIcons } from '@profullstack/favicon-generator';

const results = await generateIcons({
  inputPath: './logo.svg',
  outputDir: './public/icons',
  quality: 90,
  compressionLevel: 7,
  generateFavicon: true,
  faviconSizes: [16, 32, 48],
  verbose: true,
});

// Access generated files
results.icons.forEach((icon) => {
  console.log(`${icon.name}: ${icon.path}`);
});

Custom Icon Sizes

import { generateCustomIcons } from '@profullstack/favicon-generator';

const customSizes = [
  { size: 48, name: 'icon-48.png' },
  { size: 96, name: 'icon-96.png' },
  { size: 144, name: 'icon-144.png' },
];

const results = await generateCustomIcons('./favicon.svg', './icons', customSizes, { quality: 95 });

Using Constants

import { generateIcons, DEFAULT_ICON_SIZES, BACKGROUNDS } from '@profullstack/favicon-generator';

// Use default icon sizes
const results = await generateIcons({
  inputPath: './favicon.svg',
  outputDir: './icons',
  iconSizes: DEFAULT_ICON_SIZES,
});

// Available background colors
console.log(BACKGROUNDS.transparent); // { r: 255, g: 255, b: 255, alpha: 0 }
console.log(BACKGROUNDS.white); // { r: 255, g: 255, b: 255, alpha: 1 }
console.log(BACKGROUNDS.black); // { r: 0, g: 0, b: 0, alpha: 1 }

API Reference

generateIcons(options)

Generate PNG icons from an SVG or PNG source file.

Parameters:

  • options (Object):
    • inputPath (string, required): Path to the source .svg or .png file
    • svgPath (string, optional): Deprecated alias for inputPath, still accepted (and it may point at a .png)
    • outputDir (string, required): Output directory for generated icons
    • iconSizes (Array, optional): Array of {size, name} objects. Defaults to DEFAULT_ICON_SIZES
    • quality (number, optional): PNG quality (1-100). Default: 95
    • compressionLevel (number, optional): Compression level (0-9). Default: 9
    • generateFavicon (boolean, optional): Generate additional favicon sizes. Default: true
    • faviconSizes (Array, optional): Array of favicon sizes. Default: [16, 32]
    • verbose (boolean, optional): Enable verbose logging. Default: true

Returns: Promise

{
  icons: [
    { size: 64, name: 'icon-64.png', path: './icons/icon-64.png' },
    // ...
  ],
  faviconSizes: [
    { size: 16, path: './icons/favicon-16.png' },
    // ...
  ],
  outputDir: './icons',
  inputPath: './favicon.svg',
  inputFormat: 'svg', // 'svg' or 'png'
  rootFavicons: {
    png: './icons/favicon.png',
    svg: './icons/favicon.svg', // omitted for a PNG source
    ico: './icons/favicon.ico'
  }
}

Source Format Notes

SVG source PNG source
Scaling Rasterized losslessly at every size Resampled; upscaling softens the image
favicon.svg Written (copy of the source) Not written — no vector equivalent
Primary <link rel="icon"> /favicon.svg (image/svg+xml) /favicon.png (image/png)
Recommended input Any square viewBox Square, at least 512x512

A PNG source smaller than the largest requested icon, or one that isn't square, logs a warning: icons are still generated (upscaled and padded to fit), but the result will be softer than vector art. Supply the highest resolution you have.

isSupportedInputFile(filePath) / getInputFormat(filePath)

Helpers for validating a source path before calling generateIcons.

import { isSupportedInputFile, getInputFormat } from '@profullstack/favicon-generator';

isSupportedInputFile('logo.png'); // true
isSupportedInputFile('logo.jpg'); // false
getInputFormat('logo.png'); // 'png'
getInputFormat('logo.svg'); // 'svg'
getInputFormat('logo.jpg'); // null

generateCustomIcons(inputPath, outputDir, customSizes, additionalOptions)

Generate icons with custom sizes.

Parameters:

  • inputPath (string): Path to the source .svg or .png file
  • outputDir (string): Output directory
  • customSizes (Array): Array of {size, name} objects
  • additionalOptions (Object, optional): Additional options (quality, compressionLevel, etc.)

Returns: Promise (same as generateIcons)

Default Icon Sizes

The package generates the following icon sizes by default:

Apple Touch Icons

  • 57x57, 60x60, 72x72, 76x76
  • 114x114, 120x120, 144x144
  • 152x152, 180x180

PWA Icons

  • 192x192, 256x256, 384x384, 512x512

Favicon Sizes (optional)

  • 16x16, 32x32

Using Generated Icons in HTML

After generating your icons, add them to your HTML <head> section. See the complete example in examples/html-head-template.html.

Basic HTML Head Setup

<head>
  <!-- Favicon -->
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
  <link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png" />
  <link rel="icon" type="image/png" sizes="16x16" href="/icons/favicon-16.png" />

  <!-- Apple Touch Icons (iOS) -->
  <link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon-180x180.png" />
  <link rel="apple-touch-icon" sizes="152x152" href="/icons/apple-touch-icon-152x152.png" />
  <link rel="apple-touch-icon" sizes="144x144" href="/icons/apple-touch-icon-144x144.png" />
  <link rel="apple-touch-icon" sizes="120x120" href="/icons/apple-touch-icon-120x120.png" />
  <link rel="apple-touch-icon" sizes="114x114" href="/icons/apple-touch-icon-114x114.png" />
  <link rel="apple-touch-icon" sizes="76x76" href="/icons/apple-touch-icon-76x76.png" />
  <link rel="apple-touch-icon" sizes="72x72" href="/icons/apple-touch-icon-72x72.png" />
  <link rel="apple-touch-icon" sizes="60x60" href="/icons/apple-touch-icon-60x60.png" />
  <link rel="apple-touch-icon" sizes="57x57" href="/icons/apple-touch-icon-57x57.png" />

  <!-- Web App Manifest (PWA) -->
  <link rel="manifest" href="/manifest.json" />
  <meta name="theme-color" content="#ffffff" />

  <!-- iOS Web App -->
  <meta name="apple-mobile-web-app-capable" content="yes" />
  <meta name="apple-mobile-web-app-status-bar-style" content="default" />
  <meta name="apple-mobile-web-app-title" content="Your App" />
</head>

PWA Manifest File

Create a manifest.json file for Progressive Web App support. See examples/manifest.json for a complete example:

{
  "name": "Your App Name",
  "short_name": "App",
  "icons": [
    {
      "src": "/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any maskable"
    }
  ],
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#ffffff"
}

Platform-Specific Notes

  • iOS: Uses Apple Touch Icons (automatically adds rounded corners)
  • Android/PWA: Uses icons from manifest.json
  • Windows: Uses msapplication meta tags
  • Modern Browsers: Prefer an SVG favicon with PNG fallbacks; with a PNG source, favicon.png plus the sized PNGs cover every browser

Development

Setup

# Clone the repository
git clone https://github.com/profullstack/favicon-generator.git
cd favicon-generator

# Install dependencies
pnpm install

Running Tests

# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Run tests with coverage
pnpm test:coverage

Linting and Formatting

# Lint code
pnpm lint

# Fix linting issues
pnpm lint:fix

# Format code
pnpm format

# Check formatting
pnpm format:check

Requirements

  • Node.js >= 20.0.0
  • ESM support

Dependencies

  • sharp - High-performance image processing
  • inquirer - Interactive CLI prompts

License

MIT © profullstack

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Issues

If you encounter any issues or have questions, please file an issue on the GitHub repository.

Changelog

See CHANGELOG.md for release history.