Command Palette

Search for a command to run...

Hectal
PHASE 6Intermediate ~20 min· topic 4 of 7

Topic 6.4

Favicons and the Web App Manifest

In one line

A small set of icon links (an ICO, an SVG and a 180px Apple icon), a theme-color meta tag and a manifest.webmanifest file give your site its icon on tabs, bookmarks and home screens, and let it be installed like an app.

Think of it like this

A shop's sign and its uniform. The tiny logo on the door (the favicon) helps you find the shop in a busy street of tabs. The bigger sign over the entrance (the home-screen icon) is what you see when the shop is on your phone. The staff uniform colour (the theme colour) makes everything around the shop match. The manifest is the shop's registration form: name, opening page, colours and every size of its logo.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Favicon
The small icon on a browser tab and in bookmarks.
ICO
An old icon file format that can hold several sizes in one file. Browsers look for /favicon.ico by default.
SVG
An image format made of shapes instead of pixels, so it stays sharp at any size.
apple-touch-icon
The icon iPhones and iPads use when a site is added to the home screen.
theme-color
A meta tag suggesting a colour for the browser's bars around your page.
JSON
A text format for data: names in quotes, a colon, then a value, inside curly braces.
Web app manifest
A JSON file describing the site as an app: name, start page, colours and icons.
PWA
Progressive Web App: a website that can be installed and opened like an app.
Maskable icon
An icon with extra padding so it still looks right when the phone crops it into a circle or other shape.

Step by step

01The classic fallback

Put a favicon.ico (with 32 and 16 px inside) at the root of the site and link it. Older browsers, RSS readers and some tools only look for this.

index.htmlwhole filehtml
<link rel="icon" href="/favicon.ico" sizes="32x32">

02A sharp SVG for modern browsers

The SVG icon can adapt to dark mode by itself. Browsers that support SVG favicons prefer it.

icon.svgwhole filehtml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  <style>
    circle { fill: #0f766e; }
    @media (prefers-color-scheme: dark) { circle { fill: #5eead4; } }
  </style>
  <circle cx="16" cy="16" r="14"/>
</svg>

03Apple and theme colour

One 180 × 180 PNG for iOS. Two theme colours, one per colour scheme.

index.htmlwhole filehtml
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<meta name="theme-color" content="#0f766e" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#042f2e" media="(prefers-color-scheme: dark)">

04Write the manifest

Save it as manifest.webmanifest and serve it with the type application/manifest+json. JSON is strict: double quotes only, and no comma after the last item.

manifest.webmanifestwhole filejson
{
  "name": "Asha's Kitchen",
  "short_name": "Kitchen",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#0f766e",
  "icons": [
    { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" },
    { "src": "/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
  ]
}

05Link it and check it

Add the manifest link, then open DevTools → Application → Manifest. It lists every field, shows each icon, and reports problems such as a missing 512 px icon.

index.htmlwhole filehtml
<link rel="manifest" href="/manifest.webmanifest">
Link it and check itdiagram
Rendering diagram…

Try it yourself

  1. 1

    Add a maskable icon

    In the manifest checker, add a third icon with "purpose": "maskable". Predict the last console line, then run. Remember the comma between array items.

  2. 2

    Break the JSON on purpose

    Add a comma after the last icon (} → },). Predict what happens, run it, and read the error in the console. JSON doesn't allow trailing commas, unlike JavaScript.

  3. 3

    Recolour the icon

    In the first example, change fill='teal' to fill='crimson' in the three <img> sources. The vector stays sharp at every size. Then open DevTools → Application → Manifest on any big web app and look at its icon list.

Code & diagrams

An SVG favicon and the icon links New tab

The preview runs inside this page, so you won't see its icon on your tab; on a real site you would. `link.sizes` is a list, so `.value` gives its text.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

icon 32x32 /favicon.ico
icon image/svg+xml (inline SVG)
apple-touch-icon  /apple-touch-icon.png
manifest  /manifest.webmanifest
theme-color: #0f766e
Check a manifest like a browser would New tab

A `<script type="application/json">` is never run, so it's a handy place to keep data in a page. DevTools → Application → Manifest does these checks for real.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

has a name: true
has start_url: true
app-like display: true
192px icon: true
512px icon: true
maskable icon: false

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

A trailing comma in the manifest

In the manifest checker, add a comma after the last item of icons.

terminal
$ Console
── what you'll see ──
Uncaught SyntaxError: Unexpected token ']', ..."image/png" },
]
}"... is not valid JSON (Chrome quotes the text around the mistake)

Break #2

A transparent Apple icon

Use a PNG with a transparent background as apple-touch-icon.

terminal
$ iPhone home screen
── what you'll see ──
The icon appears on a black square.

Myth vs fact

Myth

You need 20 different favicon files.

Fact

Old generators produced dozens. Today an ICO, an SVG, a 180 px Apple PNG and two manifest PNGs (192 and 512, plus a maskable one) cover every current browser.

Myth

A manifest makes the site work offline.

Fact

The manifest only describes the app. Working offline needs a service worker (a script that can answer requests from a cache), which is a JavaScript topic.

Myth

theme-color changes the page's background.

Fact

It only suggests a colour for the browser's own interface (address bar, app title bar). Your page's colours come from CSS.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    The manifest is fetched without cookies by default. If it's behind a login, add crossorigin="use-credentials" to the manifest link, or the fetch fails.

  • ▸

    Set an id in the manifest (for example "id": "/"). Browsers identify an installed app by id, falling back to start_url; if you later change start_url without an id, browsers see a different app.

  • ▸

    Favicons are cached aggressively and separately from the page. When you change one, rename the file (icon-v2.svg) or add a query string, or users will see the old icon for weeks.

  • ▸

    In Next.js App Router, files named icon.svg, apple-icon.png, favicon.ico and manifest.ts in app/ generate these tags for you. Hectal uses favicon.ico, apple-icon.png and manifest.ts this way.

Remember this

  1. 1

    A favicon (from "favourite icon") is the small picture on a browser tab, in bookmarks and in history. If a page has no icon link, browsers ask for /favicon.ico at the root of the site anyway, so a missing one fills your server logs with 404s. The .ico format can hold several sizes in one file (16, 32 and 48 pixels).

  2. 2

    Icons are added with <link rel="icon">. The sizes attribute says the pixel size (sizes="32x32", or sizes="any" for SVG), and type says the format. An SVG icon is one small vector file that stays sharp at every size and can even switch colours for dark mode with a prefers-color-scheme media query inside it. Chromium browsers and Firefox support SVG favicons; keep the .ico as a fallback for browsers that don't.

  3. 3

    <link rel="apple-touch-icon" href="/apple-touch-icon.png"> is the icon iPhones and iPads use when someone adds your site to the home screen. Make it a 180 × 180 PNG with a solid background: iOS rounds the corners itself and fills transparent areas with black.

  4. 4

    <meta name="theme-color" content="#0f766e"> suggests a colour for the browser's interface around your page, such as the address bar on Android Chrome and the title bar of an installed app. Add a media attribute to give one colour for light mode and another for dark mode. Desktop browser tabs mostly ignore it.

  5. 5

    The web app manifest is a JSON file (JSON is a text format for data with "key": value pairs) linked with <link rel="manifest" href="/manifest.webmanifest">. It describes the site as an app: name and short_name (for small spaces under the icon), start_url (the page that opens), display (standalone hides the browser bars; others are fullscreen, minimal-ui and browser), background_color (the splash screen while it starts), theme_color, and icons with at least a 192 × 192 and a 512 × 512 PNG. A site with a manifest like this, served over HTTPS, can be installed as a Progressive Web App (PWA).

  6. 6

    Android may cut icons into circles, squircles or rounded squares. An icon with "purpose": "maskable" is designed for that: its important part sits inside a central safe zone (a circle 80% of the icon's width), and the background fills the whole square. Provide a normal (any) icon and a separate maskable one rather than one icon for both.

Explain it without notes

01

Which icon files does a modern site need, and what is each one for?

02

What does theme-color do, and how do you give different colours for light and dark mode?

03

What fields does a manifest need for a site to be installable in Chrome?

04

What is a maskable icon and why does it need a safe zone?

Practice

01

Write the head tags for a site's icons: an ICO fallback, an SVG, an Apple icon and a manifest, plus a light and a dark theme colour (#1d4ed8 and #0b1120).

02

Write a manifest for a to-do app called Tickit that opens /today in standalone mode, with a white background, a blue theme and the two required icon sizes.

Trade-offs

  • ↔

    An SVG favicon is one tiny file that adapts to dark mode, but not every browser uses it, so you still ship an ICO fallback.

  • ↔

    display: standalone makes an installed site feel like an app, but it removes the back button and address bar, so your own navigation must handle everything.

Done when you can

  • I can write the modern minimal favicon set.

  • I can make a 180 px Apple icon that looks right on iOS.

  • I can set light and dark theme-color values.

  • I can write and link a valid manifest with 192 and 512 px icons.

  • I can check icons and the manifest in DevTools → Application.