Icons & Favicons

Favicons, Apple touch icons, and web manifest icons - defined in metadata.icons and injected by bini-ssg.

Overview

Icons cover browser tabs, bookmarks, iOS home screen, and Android / PWA install. Define them with metadata.icons. bini-ssg injects route-specific icons with the correct type and sizes.

  • Favicons: icon, shortcut - SVG and ICO with sizes
  • Apple Touch: apple - 180×180 for iOS home screen
  • Manifest: manifest field + public/site.webmanifest
  • Defaults: drop files in public/ - no extra config required

Icon Types

FieldInjected asDescription
iconlink rel=iconStandard favicon with type and sizes
shortcutlink rel=shortcut iconLegacy shortcut icon
applelink rel=apple-touch-iconiOS home screen - 180×180 recommended
otherlinkOther link tags e.g. mask-icon

Icon object fields

FieldTypeDescription
urlstringURL to icon file
typestringMIME type e.g. image/svg+xml
sizesstringSize e.g. 32x32, 180x180
relstringOptional rel override

Favicons

Prefer SVG for modern browsers, with PNG and ICO as fallbacks.

app/layout.tsx
export const metadata = {
  title: 'My App',
  icons: {
    icon: [
      { url: '/favicon.svg', type: 'image/svg+xml' },
      { url: '/favicon.ico' },
      { url: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
      { url: '/favicon-16x16.png', sizes: '16x16', type: 'image/png' },
    ],
    shortcut: '/favicon.ico',
  },
}
FileSizePurpose
favicon.svganyModern browsers - scalable
favicon.ico32×32Legacy fallback
favicon-32x32.png32×32Standard tab icon
favicon-16x16.png16×16Small tab icon

Apple Touch Icons

Used when a user adds your site to the iOS home screen. iOS applies rounded corners unless you supply a precomposed asset.

app/layout.tsx
export const metadata = {
  icons: {
    apple: [
      {
        url: '/apple-touch-icon.png',
        sizes: '180x180',
        type: 'image/png',
      },
    ],
  },
}
Use a 180×180 PNG. Placing apple-touch-icon.png in public/ also works for automatic detection.

SVG vs ICO

  • SVG: vector, scalable, can use prefers-color-scheme
  • ICO: multi-size bitmap container for legacy browsers
  • PNG: widely supported middle ground
  • Best practice: SVG + 32×32 PNG + ICO + 180×180 Apple
app/layout.tsx
export const metadata = {
  icons: {
    icon: [
      { url: '/favicon.svg', type: 'image/svg+xml' },
      { url: '/favicon.ico', sizes: '32x32' },
    ],
  },
}

Manifest & Icons

The web app manifest supplies icons for Android home screen, splash, and PWA install.

app/layout.tsx
export const metadata = {
  manifest: '/site.webmanifest',
  themeColor: '#0a0a0a',
}
public/site.webmanifest
{
  "name": "My Bini.js App",
  "short_name": "Bini",
  "icons": [
    {
      "src": "/android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    },
    {
      "src": "/android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ],
  "theme_color": "#0a0a0a",
  "background_color": "#ffffff",
  "display": "standalone"
}

Default Images

Put assets in public/. Replace the defaults with your own files.

public
favicon.ico
favicon.svg
favicon-16x16.png
favicon-32x32.png
apple-touch-icon.png
android-chrome-192x192.png
android-chrome-512x512.png
og-image.png
site.webmanifest
For native packaging, logo.png in public/ is often used as the source icon for platform icon generation.

bini-ssg Injection

During vite build, bini-ssg injects icons into pre-rendered HTML. Matching rel tags are updated in place.

SourceInjected as
metadata.icons.iconlink rel=icon
metadata.icons.applelink rel=apple-touch-icon
metadata.icons.shortcutlink rel=shortcut icon
metadata.manifestlink rel=manifest
public/ defaultsPreserved from dist/index.html
Injection is best-effort and does not fail the build. Nested layouts can set different icons per segment.

Complete Example

app/layout.tsx
export const metadata = {
  title: 'My Bini.js App',
  description: 'Built with Bini.js',
  manifest: '/site.webmanifest',
  themeColor: '#0a0a0a',
  icons: {
    icon: [
      { url: '/favicon.svg', type: 'image/svg+xml' },
      { url: '/favicon.ico', sizes: '32x32' },
      {
        url: '/favicon-32x32.png',
        sizes: '32x32',
        type: 'image/png',
      },
      {
        url: '/favicon-16x16.png',
        sizes: '16x16',
        type: 'image/png',
      },
    ],
    shortcut: '/favicon.ico',
    apple: [
      {
        url: '/apple-touch-icon.png',
        sizes: '180x180',
        type: 'image/png',
      },
    ],
  },
  openGraph: {
    images: ['/og-image.png'],
  },
  twitter: {
    images: ['/og-image.png'],
  },
}
Was this helpful?