Skip to content

Latest commit

 

History

History
42 lines (28 loc) · 10.6 KB

File metadata and controls

42 lines (28 loc) · 10.6 KB

PWA manifest production-readiness audit (#694)

An audit of public/manifest.json, the icons it references, and the install-prompt-relevant <head> tags in app/layout.tsx, ahead of mainnet launch.

Findings and fixes

# Finding Severity Fix
1 Every icon file referenced by manifest.json (icons/icon-72x72.png through icons/icon-512x512.png) was missing from the repository. public/icons/ didn't exist at all. This isn't a testnet-vs-mainnet branding issue — it means install prompts have been showing a broken or generic fallback icon (or Chrome's installability check may have been failing outright) in every environment, not just production. Critical Generated a full icon set from a new source SVG (public/icons/icon-source.svg) via scripts/generate-pwa-icons.mjs (uses sharp, added as a devDependency). See "Icon design" below.
2 No apple-touch-icon link tag existed anywhere. iOS's "Add to Home Screen" does not read the manifest's icons array — it specifically needs a <link rel="apple-touch-icon">. Without it, users get a screenshot of the page as their home-screen icon. Critical Added <link rel="apple-touch-icon" href="/icons/apple-touch-icon.png" sizes="180x180" /> in app/layout.tsx, generated at 180×180 (Apple's current recommended size), flattened to remove the alpha channel since iOS renders transparency in home-screen icons inconsistently.
3 msapplication-config pointed at /icons/browserconfig.xml, which also didn't exist (same missing-icons/-directory problem). Medium Generated public/icons/browserconfig.xml and the mstile-150x150.png tile it references. Legacy (Windows pinned-tile), but cheap to fix correctly while already touching this directory.
4 manifest.json declared "splash_pages": null, which is not a field in the Web App Manifest spec. Harmless (every consumer ignores unknown fields) but dead weight suggesting the file was copied from an unrelated template. Low Removed. Added "id": "/" instead, which is a real, recommended field for a stable app identity across future icon/URL changes.
5 name / short_name / description were checked for testnet-era wording ("testnet", "staging", "dev build", "placeholder") and found clean — "Invoice Liquidity Network" / "ILN" / "Decentralized invoice factoring on Stellar" are already production-appropriate. — (no issue) No change. Added a regression test asserting this (__tests__/pwa-manifest.test.ts) so it can't silently regress.
6 public/screenshots/*.png (freelancer_dashboard.png, lp_dashboard.png, marketplace.png) exist but are not wired into the manifest, and should not be — they depict a differently-branded fictional product ("The Fiscal Atelier / Liquidity Provider Hub"), not the actual ILN UI. They aren't referenced anywhere in app//src/ either, so they're inert today, but wiring them into the manifest's optional screenshots field (which enables a richer Android install card) would ship a fake UI mockup as if it were the real app. Note only Left as-is; flagged here so nobody adds them to screenshots assuming they're real captures. If richer install screenshots are wanted, they need to be actual captures of the live app.

Icon design

public/icons/icon-source.svg is the single source of truth: the app's real --color-primary background (#3d627f, matching manifest.json's theme_color and the design tokens in app/globals.css) with a white "ILN" monogram. Content is kept inside the maskable "safe zone" (an inscribed circle at 80% of the icon's diameter, per the maskable icon guidance), so the same file is valid for both purpose: "any" and purpose: "maskable" — which is why manifest.json keeps the existing "maskable any" combined-purpose entries rather than needing to split into separate icon sets.

This is a clean placeholder in the sense that it's a simple monogram, not a professionally designed final logo — but it is not a testnet/dev placeholder; it uses the app's real, current brand color and no throwaway text. If/when a proper logo exists, replace icon-source.svg and re-run:

node scripts/generate-pwa-icons.mjs

which regenerates every manifest icon size, the apple-touch-icon, and the Windows tile from the one source file.

Automated verification added

  • __tests__/pwa-manifest.test.ts (9 tests): validates manifest.json's required fields, absence of testnet/placeholder wording, that every referenced icon file exists on disk and matches its declared sizes, presence of the 192×192/512×512 sizes Chrome's installability check requires, valid purpose values, and that the apple-touch-icon exists at 180×180 with no alpha channel. This is exactly the class of bug finding #1 above was — a manifest that looks correct in a JSON diff but references files that were never committed.
  • e2e/pwa-manifest.spec.ts: live-server checks that /manifest.json and every icon it references actually resolve with a 200 and the right content type against a running Next.js server, and that the home page's <head> links both the manifest and the apple-touch-icon. This spec could not be executed in the environment this audit was performed inpnpm dev did not come up within several minutes here, for reasons unrelated to this change (this same environment showed similarly heavy startup overhead running the existing unit test suite). The spec follows the exact pattern of the pre-existing e2e/security-txt.spec.ts and is wired into the existing playwright.config.ts webServer setup, so it should run normally in CI or a working local dev environment — but that has not been confirmed here, and it should be run once before relying on it.

What this audit did NOT verify

Per the issue's own requirement, install-flow testing on a real Android device/emulator and a real iOS device/simulator needs an actual mobile OS and browser, which this environment does not have. That has not been done. Before sign-off, a maintainer with access to real devices (or BrowserStack/similar) should confirm:

  • Android (Chrome): the install prompt/banner appears, uses the correct icon (not a generic globe/blank icon), and the installed app opens in standalone mode with the right icon on the home screen and app drawer.
  • Android: the maskable icon renders correctly under at least one non-circular mask shape (e.g. squircle) if the device/launcher supports checking this (or verify via https://maskable.app/editor using icon-source.svg).
  • iOS Safari: "Add to Home Screen" produces the ILN icon (not a page screenshot), and launching from the home screen opens in standalone mode (no Safari chrome), matching apple-mobile-web-app-capable.
  • Confirm e2e/pwa-manifest.spec.ts passes against a real running server (pnpm exec playwright test e2e/pwa-manifest.spec.ts).

This document should not be read as "install flow verified" — it's "manifest and asset correctness verified statically; device-level install flow still needs a human with real devices."