PWA Essentials: Web App Manifest Configuration Guide and Generator Implementation#

Recently converted a web app to PWA for app store submission. Web App Manifest seemed simple at first, but the details caught me off guard. Built a generator tool and documented the key configuration points.

What is Manifest and Why PWA Needs It?#

Simply put, manifest.json is the “ID card” for your PWA. The browser uses it to know:

  • What’s the app name
  • What’s the launch icon
  • Should it run fullscreen or in browser mode
  • Theme color and background color

Without manifest, your web app is just a regular webpage. No “Add to Home Screen”, no offline support, no app store submission.

A minimal manifest:

{
  "name": "My PWA App",
  "short_name": "PWA",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#000000",
  "icons": [
    {
      "src": "/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ]
}

Four Display Modes Explained#

The display field determines how your app appears. This is where most developers stumble:

"display": "standalone"

Most native-like mode. Hides browser address bar and tabs, showing only app content. Users feel like using a standalone app.

Best for: Tools, games, content apps

2. fullscreen#

"display": "fullscreen"

Complete fullscreen, even hides status bar. For immersive experiences.

Best for: Games, video players, presentation tools

Note: iOS Safari doesn’t support fullscreen, falls back to standalone

3. minimal-ui#

"display": "minimal-ui"

Keeps minimal browser controls (back button). Between standalone and browser.

Best for: Apps where users should know it’s a webpage

4. browser#

"display": "browser"

Standard browser mode with all controls. Basically a regular webpage.

Best for: Content sites, blogs

Icons Configuration Pitfalls#

Icon configuration is the most error-prone part. Docs say provide multiple sizes, but which ones?

Required Sizes#

"icons": [
  { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
  { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
]

192x192 is Android’s minimum requirement. 512x512 is for splash screens.

"icons": [
  { "src": "/icon-72.png", "sizes": "72x72", "type": "image/png" },
  { "src": "/icon-96.png", "sizes": "96x96", "type": "image/png" },
  { "src": "/icon-128.png", "sizes": "128x128", "type": "image/png" },
  { "src": "/icon-144.png", "sizes": "144x144", "type": "image/png" },
  { "src": "/icon-152.png", "sizes": "152x152", "type": "image/png" },
  { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
  { "src": "/icon-384.png", "sizes": "384x384", "type": "image/png" },
  { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
]

Maskable Icons (Android Adaptive Icons)#

Android 8.0+ supports adaptive icons, requiring separate configuration:

{
  "src": "/icon-maskable-192.png",
  "sizes": "192x192",
  "type": "image/png",
  "purpose": "maskable"
}

Key point: Maskable icons need 20% safe zone padding because the system clips them into circles, rounded rectangles, etc.

Purpose Field Values#

"purpose": "any"            // Default, standard icon
"purpose": "maskable"       // Adaptive icon
"purpose": "any maskable"   // Supports both

Shortcuts: Long-press Quick Actions#

Similar to native app 3D Touch shortcuts:

"shortcuts": [
  {
    "name": "New Task",
    "short_name": "New",
    "description": "Quickly create a new task",
    "url": "/tasks/new",
    "icons": [{ "src": "/icons/new-task.png", "sizes": "96x96" }]
  },
  {
    "name": "Search",
    "short_name": "Search",
    "url": "/search"
  }
]

Limit: Maximum 4 shortcuts. Android and Windows support it, iOS doesn’t.

Categories and Screenshots: App Store Optimization#

Important when submitting to Google Play or Microsoft Store:

{
  "categories": ["productivity", "utilities"],
  "screenshots": [
    {
      "src": "/screenshots/home.png",
      "sizes": "1080x1920",
      "type": "image/png",
      "label": "Home Screen"
    },
    {
      "src": "/screenshots/settings.png",
      "sizes": "1080x1920",
      "type": "image/png",
      "label": "Settings Page"
    }
  ]
}

Categories options: games, social, entertainment, productivity, utilities, etc.

Implementation: Building the Generator#

Built an online tool for easy configuration: Manifest Generator

Core implementation is straightforward - a form + JSON serialization:

interface ManifestData {
  name: string
  short_name: string
  description: string
  start_url: string
  display: string
  orientation: string
  theme_color: string
  background_color: string
  icons: IconEntry[]
}

const manifestJSON = JSON.stringify(manifest, null, 2)

But several details matter:

1. Template System#

Different frameworks have slightly different PWA configurations:

const templates = {
  basic: { /* Basic config */ },
  nextjs: { /* Next.js specific */ },
  react: { /* CRA specific */ }
}

Next.js typically uses /icons/icon-192x192.png, while CRA uses /logo192.png.

2. Dynamic Icon Array Management#

const addIcon = () => {
  setManifest(prev => ({
    ...prev,
    icons: [...prev.icons, { src: '', sizes: '', type: 'image/png' }]
  }))
}

const removeIcon = (index: number) => {
  setManifest(prev => ({
    ...prev,
    icons: prev.icons.filter((_, i) => i !== index)
  }))
}

3. Filter Empty Icons#

When generating JSON, filter out unfilled icons:

const filteredIcons = icons.filter(icon => icon.src || icon.sizes)

4. Color Picker Sync#

Color input supports two methods: color picker + text input, need to keep them in sync:

<input type="color" value={manifest.theme_color} onChange={e => updateField('theme_color', e.target.value)} />
<input type="text" value={manifest.theme_color} onChange={e => updateField('theme_color', e.target.value)} />

Common Issues Troubleshooting#

1. “Add to Home Screen” Not Showing#

Checklist:

  • Is manifest.json linked via <link rel="manifest">
  • Is it running on HTTPS (localhost exempted)
  • Do icons meet 192x192 and 512x512 requirements
  • Is Service Worker registered

2. iOS Icons Not Working#

iOS doesn’t fully support manifest. Need extra meta tags:

<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" content="My App">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">

3. Theme Color Not Applying#

theme_color affects browser address bar color, but only works in Android Chrome. iOS Safari needs apple-mobile-web-app-status-bar-style.

4. White Splash Screen#

Check if background_color matches your actual page background. Splash screen shows background_color + name + icon.

Testing Tools#

Summary#

Web App Manifest is foundational for PWA, but has many details. Recommend using a generator tool for quick setup, then fine-tune based on actual needs.

Key configuration points:

  • display: standalone is most universal
  • Icons: at minimum provide 192x192 and 512x512
  • iOS: requires extra meta tags
  • theme_color and background_color: should match your design

Related: PWA Icon Generator | Service Worker Generator