BALKE/ASSOCIATES← All tools

PWA TOOL / 004

PWA asset generator.

Create installable app icons, maskable safe-area variants, and a configured web manifest from one source image.

STANDARD

MASKABLE

APPLICATION MANIFEST

LAUNCH & IDENTITY

The App ID is a stable URL-shaped identity chosen by you—not an app-store ID. For a site-wide PWA, / is usually correct. Avoid changing it after users install the app.

Preview site.webmanifest
{
  "id": "/",
  "name": "My Application",
  "short_name": "My App",
  "description": "A progressive web application.",
  "start_url": "/",
  "scope": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#07111f",
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "/icons/maskable-icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "maskable"
    },
    {
      "src": "/icons/maskable-icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ]
}

INSTALL BUTTON KIT

Let visitors install it.

The downloaded package includes React and plain JavaScript install buttons, plus automatic iPhone and iPad instructions.

Preview React component
"use client";

import { useEffect, useState } from "react";

interface InstallPromptEvent extends Event {
  prompt(): Promise<void>;
  userChoice: Promise<{ outcome: "accepted" | "dismissed" }>;
}

export function InstallPwaButton() {
  const [prompt, setPrompt] = useState<InstallPromptEvent | null>(null);
  const [showIosHelp, setShowIosHelp] = useState(false);

  useEffect(() => {
    const standalone = window.matchMedia("(display-mode: standalone)").matches;
    const ios = /iphone|ipad|ipod/i.test(navigator.userAgent);
    if (!standalone && ios) setShowIosHelp(true);

    const capture = (event: Event) => {
      event.preventDefault();
      setPrompt(event as InstallPromptEvent);
    };
    window.addEventListener("beforeinstallprompt", capture);
    return () => window.removeEventListener("beforeinstallprompt", capture);
  }, []);

  async function install() {
    if (!prompt) return;
    await prompt.prompt();
    await prompt.userChoice;
    setPrompt(null);
  }

  if (prompt) return <button onClick={install}>Install App</button>;
  if (showIosHelp) return <p>To install: tap Share, then Add to Home Screen.</p>;
  return null;
}