Skip to content

Repository files navigation

Favicon

Fetch, convert, and cache favicons for any website in your Laravel app.

Given a site URL, the package discovers the best available icon source (preferring an SVG over an ICO over a raster PNG/WebP/AVIF over a JPG), downloads it, and converts it into whichever size/format you ask for — caching the result on disk so subsequent requests are instant until the TTL expires.

Requirements

  • PHP 8.2+
  • The imagick PHP extension, ideally built with the librsvg delegate (for SVG rasterization) and libheif delegate (for AVIF)
  • Laravel 10, 11, or 12

Installation

composer require backstage/favicon

Optionally publish the config:

php artisan vendor:publish --tag=favicon-config

Usage

Facade

use Backstage\Favicon\Facades\Favicon;

// Absolute filesystem path
$path = Favicon::for('https://github.com')->get('png', 32);

// Public URL (served from the configured disk)
$url = Favicon::for('https://github.com')->url('webp', 64);

// The original SVG, only if the discovered source was actually an SVG
$url = Favicon::for('https://github.com')->url('svg');

// Force a re-fetch from the source site, ignoring the TTL
$url = Favicon::for('https://github.com')->refresh()->url('png', 32);

Supported types: png, jpg, webp, avif, and svg (pass-through only — a raster source can't be vectorized).

Blade component

<x-favicon url="https://github.com" size="32" type="png" class="rounded" />

Eloquent trait

use Backstage\Favicon\Concerns\HasFavicon;

class Site extends Model
{
    use HasFavicon;

    // Reads from $site->website by default; override per-model:
    protected string $faviconSource = 'homepage_url';

    // Optional: override the package-wide default type/size for this model.
    protected string $faviconType = 'webp';
    protected int $faviconSize = 64;
}
$site->favicon;                 // accessor, uses $faviconType/$faviconSize (or config defaults)
$site->faviconUrl();            // same as above
$site->faviconUrl('png', 32);   // explicit args still win over both

Artisan command

# Fetch the default type/size
php artisan favicon:fetch https://github.com

# Pre-warm every configured size for specific types
php artisan favicon:fetch https://github.com --types=png,webp --sizes=16,32,180

# Ignore the TTL
php artisan favicon:fetch https://github.com --force

# Dispatch to the queue instead of running synchronously
php artisan favicon:fetch https://github.com --queue

Queued pre-warming

use Backstage\Favicon\Jobs\FetchFaviconJob;

FetchFaviconJob::dispatch('https://github.com', types: ['png', 'webp'], sizes: [32, 180]);

->warm() (used internally by the job/command) also generates a multi-resolution favicon.ico, an apple-touch-icon.png, and a site.webmanifest with Android Chrome icons, per the generate config.

How source discovery works

For a given site, the package:

  1. Fetches the page and parses <link rel="icon">, rel="shortcut icon", rel="apple-touch-icon", rel="apple-touch-icon-precomposed", and rel="mask-icon" tags, plus <link rel="manifest"> and its icons array.
  2. Falls back to /favicon.ico at the domain root.
  3. Ranks every candidate: SVG first, then ICO, then PNG/WebP/AVIF (largest declared size wins), then JPG.
  4. Downloads the best candidate and sniffs its real type from magic bytes (not the Content-Type header, which is often wrong).
  5. If the source is a multi-frame .ico, the largest embedded frame is used.

Storage

No database table is used. Each fetched favicon is cached under the configured disk (default public) at:

favicons/{domain}/
├── meta.json                # source url/type/hash + fetched_at, used for TTL checks
├── source.{ext}              # cached original bytes
├── icon.svg                  # only when the source is svg
├── variants/{type}/{size}.{ext}
├── favicon.ico
├── apple-touch-icon.png
├── android-chrome-{size}x{size}.png
└── site.webmanifest

A favicon is considered fresh for favicon.ttl_days (default 30) days from fetched_at; after that, the next resolution re-fetches from the source site.

Testing

composer test

License

MIT.

About

Fetch, convert, and cache favicons for any website in your Laravel app.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages