pwa-review

The PWA URL to analyze (e.g., https://example.com)

<pwa-review>

PWA Review Skill

A comprehensive Progressive Web App audit that goes beyond standard Lighthouse testing. This skill analyzes PWAs across 11 categories with a 185-point scoring system, including advanced features and iOS-specific compatibility checks that typical audits miss.

Scoring Overview

CategoryPointsFocus
Manifest Compliance20Essential manifest fields
Advanced Manifest15Enhanced manifest features + iOS splash
Service Worker & Caching33SW implementation quality + caching strategies
Offline Capability19Offline functionality + storage + sync triggers
Installability13Install requirements
Security16Security measures
Performance Signals17Performance optimization + network detection
UX & Accessibility27User experience + iOS safe areas + mobile dropdowns + themes
SEO & Discoverability7Search optimization
PWA Advanced17Cutting-edge PWA features
iOS Compatibility1iOS-specific meta tags (bonus)

Grading Scale: A+ (90%+), A (80-89%), B (70-79%), C (60-69%), D (40-59%), F (<40%)


Execution Workflow

When the user invokes /pwa-review <url>, follow these steps precisely:

Step 1: Fetch Target HTML

Use WebFetch to retrieve the target URL's HTML content.

WebFetch: {url}
Prompt: "Return the complete HTML source code. I need to analyze the head section for PWA-related tags including manifest link, meta tags, and inline scripts."

Step 2: Extract PWA Resources

From the HTML, identify:

Manifest URL:

  • Look for <link rel="manifest" href="...">
  • Convert relative URLs to absolute using the base URL
  • If not found, note as CRITICAL issue

Service Worker Registration:

  • Search for navigator.serviceWorker.register('...') or navigator.serviceWorker.register("...")
  • Extract the SW file path
  • If not found, note as CRITICAL issue

Meta Tags to Extract:

  • <meta name="theme-color" content="...">
  • <meta name="apple-mobile-web-app-capable" content="...">
  • <meta name="apple-mobile-web-app-status-bar-style" content="...">
  • <meta name="mobile-web-app-capable" content="...">
  • <meta name="viewport" content="..."> (check for viewport-fit=cover)
  • <meta http-equiv="Content-Security-Policy" content="...">
  • <link rel="apple-touch-icon" href="...">
  • <link rel="apple-touch-startup-image" ...> (iOS splash screens)

Step 3: Fetch Manifest

If manifest URL was found, use WebFetch to retrieve it:

WebFetch: {manifest_url}
Prompt: "Return the complete manifest.json content as raw JSON."

If manifest fetch fails (CORS, 404, etc.), score manifest categories as 0 and continue.

Step 4: Fetch Service Worker

If service worker URL was found, use WebFetch to retrieve it:

WebFetch: {sw_url}
Prompt: "Return the complete service worker JavaScript code."

If SW fetch fails, score SW-related categories as 0 and continue.

Step 5: Analyze & Score

Evaluate each category using the detailed checklist below. Track:

  • Passed items (full points)
  • Failed items (0 points) - record as issues
  • Partial items (partial points where applicable)

Step 6: Generate Report

Output a markdown report following the template at the end of this document.


Detailed Scoring Checklist

Category 1: Manifest Compliance (20 points)

CheckPointsHow to Verify
name field present and non-empty2manifest.name exists and length > 0
short_name present (≤12 chars recommended)2manifest.short_name exists
icons array with 192x192 PNG4icons array has item with sizes="192x192"
icons array with 512x512 PNG4icons array has item with sizes="512x512"
start_url defined2manifest.start_url exists
display mode set (standalone/fullscreen/minimal-ui)2manifest.display is one of allowed values
background_color specified2manifest.background_color exists (hex/rgb/named)
theme_color specified2manifest.theme_color exists

Critical Blocker: If manifest is missing entirely, this category scores 0/20.

Category 2: Advanced Manifest Features (15 points)

CheckPointsHow to Verify
description field present1manifest.description exists
screenshots array for install UI2manifest.screenshots array with ≥1 item
shortcuts array for quick actions2manifest.shortcuts array with ≥1 item
categories array defined1manifest.categories exists
orientation preference set1manifest.orientation exists
dir and lang for i18n1manifest.dir OR manifest.lang exists
id field for app identity1manifest.id exists
scope properly defined1manifest.scope exists
Maskable icon present1icons array has item with purpose="maskable" or "any maskable"
note_taking object1manifest.note_taking exists (ChromeOS lock screen notes)
widgets array1manifest.widgets exists (Windows 11 Widgets Board)
iOS splash screens present2<link rel="apple-touch-startup-image"> tags for multiple device sizes

iOS Splash Screen Note: iOS requires separate <link rel="apple-touch-startup-image"> tags for each device size. Without these, iOS shows a blank white screen during PWA launch. Check for multiple media queries covering different device dimensions.

Category 3: Service Worker & Caching (33 points)

CheckPointsHow to Verify
SW registered in HTML2navigator.serviceWorker.register() found
install event handler present3SW contains addEventListener('install', ...) or self.oninstall
activate event handler present3SW contains addEventListener('activate', ...) or self.onactivate
fetch event handler present4SW contains addEventListener('fetch', ...) or self.onfetch
Cache API usage (caches.open/put/match)3SW contains caches.open or cache.put or cache.match
Cache versioning/naming strategy2SW has cache name variable (CACHE_NAME, CACHE_VERSION, etc.)
Old cache cleanup in activate2activate handler deletes old caches
Background Sync support2SW contains addEventListener('sync', ...) or addEventListener('periodicsync', ...)
Workbox usage (bonus, not required)1SW imports workbox or uses workbox.* methods
skipWaiting() usage1SW contains self.skipWaiting() for instant activation
clients.claim() usage1SW contains clients.claim() for immediate control
Navigation preload1SW uses navigationPreload.enable()
Stale-while-revalidate pattern1fetch handler serves cache then updates in background
Push event handler1SW contains addEventListener('push', ...)
notificationclick handler1SW contains addEventListener('notificationclick', ...)
Notification action buttons1Push notifications include actions array OR notificationclick checks event.action
Multiple caching strategies2SW uses different strategies for different routes (CacheFirst, NetworkFirst, StaleWhileRevalidate)
Cache expiration config1SW has maxEntries or maxAgeSeconds for cache pruning
SW message handler1SW contains addEventListener('message', ...) for client communication

Critical Blocker: If no service worker, this category scores 0/33.

Caching Strategies Note: Production-grade PWAs should use different caching strategies based on resource type:

  • CacheFirst: Static assets, fonts, images (rarely change)
  • NetworkFirst: API responses, dynamic content (freshness matters)
  • StaleWhileRevalidate: JS/CSS bundles (speed + freshness balance) Look for patterns like new CacheFirst(), new NetworkFirst(), or explicit strategy patterns in fetch handlers.

Cache Expiration Note: Without expiration limits, caches grow unbounded and can exceed storage quotas. Look for ExpirationPlugin with maxEntries or maxAgeSeconds, or custom cleanup logic in the fetch handler.

Category 4: Offline Capability (19 points)

CheckPointsHow to Verify
Offline fallback page defined3SW caches and serves an offline.html or similar
App shell resources precached3install event caches core HTML/CSS/JS files
Offline indicator in UI (code pattern)2Code checks navigator.onLine or listens to online/offline events
Network-first or cache-first strategy evident2fetch handler has clear strategy pattern
Update prompt shown to user1Code handles SW update with user notification (e.g., "New version available")
Graceful update flow1Update doesn't force reload without warning, user can choose when to update
Update state persistence1localStorage flag prevents update prompt re-appearing after update (e.g., pwa-just-updated)
Touch event double-fire prevention1Update/action handlers prevent duplicate execution from onClick + onTouchEnd
Persistent storage request1Code uses navigator.storage.persist() to prevent iOS data eviction
IndexedDB offline storage1Code uses indexedDB.open() or idb library for structured offline data
Storage quota monitoring1Code uses navigator.storage.estimate() for storage health checks
Background sync client trigger1Client triggers registration.sync.register() when coming back online
Periodic sync registration1Client registers registration.periodicSync.register() on app init

Update UX Note: Good PWAs notify users when updates are available and let them choose when to apply the update. Look for patterns like useRegisterSW, workbox-window, or custom SW update handling with user-facing notifications.

Background Sync Client Trigger Note: Having a sync event handler in the service worker is not enough. The client must explicitly trigger background sync when coming back online by calling navigator.serviceWorker.ready.then(reg => reg.sync.register('sync-pending-requests')) in the online event listener. Without this, offline requests remain queued indefinitely.

Periodic Sync Registration Note: The service worker periodicsync event handler must be complemented by client-side registration during app initialization. Look for registration.periodicSync.register('sync-content', { minInterval: ... }) wrapped in a permission check (navigator.permissions.query({ name: 'periodic-background-sync' })). This enables automatic background content updates even when the app is closed.

Update State Note: After a user clicks "Update", the PWA reloads. Without state management, the update prompt may immediately re-appear because the new service worker is still "waiting". Use localStorage flags (e.g., pwa-just-updated with timestamp) to suppress the prompt for a brief period (30 seconds) after update completion. Also implement double-fire prevention for touch handlers - on iOS, both onClick and onTouchEnd may fire, causing duplicate updates.

Offline Storage Note: For complex PWAs with user-generated content, localStorage alone is insufficient. Use IndexedDB for structured data storage (images, generation history, preferences). Request persistent storage with navigator.storage.persist() to prevent iOS from evicting data after 7 days of inactivity. Monitor storage quota with navigator.storage.estimate() to warn users before running out of space.

Category 5: Installability Requirements (13 points)

CheckPointsHow to Verify
Served over HTTPS3URL starts with https://
Valid manifest linked in HTML2<link rel="manifest"> exists with valid href
Service worker with fetch handler2Covered in SW category, cross-check
192x192 icon present1Covered in manifest, cross-check
512x512 icon present1Covered in manifest, cross-check
apple-touch-icon for iOS1<link rel="apple-touch-icon"> in HTML
beforeinstallprompt handled2HTML/JS contains beforeinstallprompt event listener
Custom install UI1Code shows/hides custom install button

Note: prefer_related_applications: true in manifest BLOCKS browser install prompt - flag as CRITICAL if found.

Category 6: Security Measures (16 points)

CheckPointsHow to Verify
HTTPS enforced2URL is https:// (duplicate check for emphasis)
Content Security Policy present3CSP meta tag or mention in SW/HTML
Subresource Integrity (SRI) on scripts2<script> tags have integrity="sha..."
No mixed content2No http:// resources loaded on https:// page
scope restricted appropriately1manifest.scope doesn't expose unnecessary paths
Cross-Origin Isolation (COOP/COEP)2Headers: Cross-Origin-Opener-Policy, Cross-Origin-Embedder-Policy
HSTS header1Strict-Transport-Security header (note: not detectable from HTML)
X-Content-Type-Options1nosniff header present (note: not detectable from HTML)
Referrer-Policy1Appropriate referrer policy set via meta or header
Permissions-Policy1Feature policy defined (note: not detectable from HTML)

Note: Some security headers (HSTS, X-Content-Type-Options, Permissions-Policy) cannot be verified from HTML alone. Mark as "Unable to verify" unless response headers are available.

Category 7: Performance Signals (17 points)

CheckPointsHow to Verify
No render-blocking scripts in head2Scripts have defer/async or are at body end
Images have lazy loading2<img loading="lazy"> or Intersection Observer usage
Resource hints present2<link rel="preload/prefetch/preconnect"> found
Code splitting indicators2Multiple JS chunks or dynamic import() usage
Font optimization2font-display: swap or preloaded fonts
LCP optimization signals1Hero image preloaded, above-fold content prioritized
INP optimization signals1No long tasks, event handlers optimized (qualitative)
CLS prevention1Images have width/height, no layout shifts expected
Critical CSS inlined1Critical styles in <head> or preloaded
Compression headers1Server returns Content-Encoding: gzip or br (note: verify via DevTools)
Bundle chunking strategy1Build uses manualChunks, vendor splitting, or separate runtime chunks
Network Information API usage1Code uses navigator.connection for adaptive behavior on slow networks

Compression Note: Gzip/Brotli compression can reduce bundle sizes by 60-80%. This cannot be verified from HTML alone - check Network tab in DevTools for Content-Encoding response header. Build tools like vite-plugin-compression can generate pre-compressed .gz and .br files.

Bundle Chunking Note: Good build configurations split vendor dependencies (React, UI libraries, i18n) into separate chunks. Look for patterns like manualChunks in Vite/Rollup config or webpack's splitChunks. This enables better caching (vendor chunks change less frequently) and parallel loading.

Network Information API Note: The Network Information API (navigator.connection) enables adaptive behavior based on connection quality. Look for patterns that check connection.effectiveType (4g/3g/2g/slow-2g), connection.saveData, or connection.downlink. PWAs can reduce image quality, disable prefetching, or extend API timeouts on slow connections. Example:

const conn = navigator.connection;
if (conn?.effectiveType === '2g' || conn?.saveData) {
  // Load low-quality images, disable autoplay, extend timeouts
}

Category 8: UX & Accessibility (27 points)

CheckPointsHow to Verify
Responsive viewport meta2<meta name="viewport" content="width=device-width, initial-scale=1">
viewport-fit=cover for safe areas2Viewport meta includes viewport-fit=cover (required for iOS notch/Dynamic Island)
Safe area CSS usage2Code uses env(safe-area-inset-*) for fixed/sticky elements
Semantic HTML structure2<main>, <nav>, <header>, <footer> tags present
ARIA landmarks or roles2role="..." or aria-* attributes found
Language declared2<html lang="..."> attribute present
Touch-friendly targets2No evidence of tiny click targets (qualitative)
Touch event handling for iOS1Critical buttons have onTouchEnd handlers or touch-manipulation CSS
Focus indicators visible1:focus styles not removed, visible outlines (qualitative)
Skip to main content link1Skip link present for keyboard navigation
Mobile dropdown positioning2Dropdowns use fixed on mobile, absolute on desktop with proper margins
Dropdown safe area handling1Dropdowns apply safe-area-inset-right/left for notch devices
Theme consistency (light/dark)2All UI elements have both light and dark: variants in Tailwind/CSS
Dark overlay theme pairs1bg-black/X patterns have dark: prefix (e.g., bg-white/60 dark:bg-black/60)
Border visibility pairs1border-white/X has light alternative (e.g., border-zinc-200 dark:border-white/10)
Hover state theme pairs1Hover backgrounds have both variants (e.g., hover:bg-zinc-100 dark:hover:bg-white/10)
Gradient theme support1Gradient stops have variants (e.g., from-white/80 dark:from-black/80)
Contextual text-white1White text only on colored backgrounds, not transparent overlays

iOS Safe Area Note: iPhone notch and Dynamic Island require special handling. Without viewport-fit=cover and env(safe-area-inset-*) CSS, content may be obscured or buttons may be unreachable in PWA standalone mode. Fixed headers should use padding-top: env(safe-area-inset-top) and bottom navigation should account for safe-area-inset-bottom.

Touch Event Note: On iOS, onClick handlers may not fire reliably in PWA mode. Critical action buttons (update, install, submit) should include onTouchEnd handlers as backup. The CSS property touch-manipulation prevents double-tap zoom delays.

Mobile Dropdown Positioning Note: Dropdowns positioned with absolute relative to a small parent element (like a button) often extend beyond the viewport on mobile. Solution: Use fixed positioning on mobile to break out of the parent's positioning context, then use left-4 right-4 (or similar) for consistent margins instead of transform centering (left-1/2 -translate-x-1/2). On desktop (sm: breakpoint), revert to absolute with right-0 for proper alignment. Always apply safe-area-inset-right via inline style for notch devices.

Theme Consistency Note: In Tailwind CSS projects, all UI elements should have both light and dark variants. Look for patterns like bg-zinc-100 dark:bg-zinc-900. Hardcoded colors without a dark: counterpart (e.g., bg-zinc-900 alone) will appear incorrectly in light mode. Common problem areas: tooltips, buttons, borders, and dropdown backgrounds.

Extended Theme Checks Note: Alpha/opacity-based colors (bg-black/60, border-white/10, from-black/80) are commonly used for dark mode but invisible or wrong in light mode. Each pattern needs a light mode counterpart:

  • bg-black/60bg-white/60 dark:bg-black/60
  • border-white/10border-zinc-200 dark:border-white/10
  • hover:bg-black/10hover:bg-zinc-100 dark:hover:bg-white/10
  • from-black/80from-white/80 dark:from-black/80
  • text-white on overlays → text-zinc-900 dark:text-white These patterns are frequently missed because they work in dark mode (the default design) but break in light mode.

Category 9: SEO & Discoverability (7 points)

CheckPointsHow to Verify
<title> tag present1HTML has <title> with content
Meta description2<meta name="description" content="...">
Open Graph tags2og:title, og:description, og:image present
Canonical URL1<link rel="canonical" href="...">
Structured data (JSON-LD)1<script type="application/ld+json"> found

Category 10: PWA Advanced Capabilities (17 points)

CheckPointsHow to Verify
handle_links preference2manifest.handle_links exists (preferred/auto/not-preferred)
launch_handler defined2manifest.launch_handler object exists
file_handlers array2manifest.file_handlers with accept types
protocol_handlers array2manifest.protocol_handlers for custom protocols
share_target defined2manifest.share_target object exists
display_override array1manifest.display_override for fallback displays
edge_side_panel for Edge1manifest.edge_side_panel object exists
scope_extensions1manifest.scope_extensions array exists
related_applications (informational)1manifest.related_applications exists
prefer_related_applications is false/absent1Value is false or field is missing (true = CRITICAL issue)
Web Push configured1VAPID or gcm_sender_id in manifest
Notification permission UX1Permission requested after user action, not on load

Category 11: iOS Compatibility Bonus (1 point)

CheckPointsHow to Verify
Complete iOS meta tag set1Has apple-mobile-web-app-capable, apple-mobile-web-app-status-bar-style, AND mobile-web-app-capable

Note: This is a bonus point for PWAs that have complete iOS compatibility meta tags. The individual checks are scored in their respective categories, but having the complete set demonstrates attention to cross-platform compatibility.


Issue Classification

Critical Issues (Must Fix)

  • Missing manifest file
  • Missing service worker
  • No fetch event handler in SW
  • prefer_related_applications: true (blocks install)
  • Not served over HTTPS
  • Missing required icons (192x192, 512x512)

Warnings (Should Fix)

  • Missing theme_color/background_color
  • No offline fallback page
  • No CSP header/meta
  • Missing apple-touch-icon
  • No cache versioning strategy
  • Missing meta description
  • No skipWaiting/clients.claim
  • No beforeinstallprompt handling
  • Missing viewport-fit=cover (iOS safe areas won't work)
  • No env(safe-area-inset-*) usage for fixed elements
  • Missing iOS splash screens
  • No update notification UX for users
  • No update state persistence (prompt may re-appear after update)
  • Dropdowns use absolute positioning without mobile viewport handling
  • Hardcoded colors without light/dark theme variants
  • bg-black/X patterns without dark: prefix (invisible in light mode)
  • border-white/X patterns without light alternative (invisible in light mode)
  • hover:bg-black/X or hover:bg-white/X without theme pair
  • Gradient stops without theme variants
  • text-white on transparent/overlay backgrounds (unreadable in light mode)

Informational (Nice to Have)

  • Missing advanced manifest features
  • No PWA advanced capabilities
  • No structured data
  • Missing shortcuts
  • No navigation preload
  • No stale-while-revalidate
  • No persistent storage request (iOS data may be evicted)
  • No IndexedDB usage (limited to localStorage)
  • No storage quota monitoring
  • No compression headers detected
  • No bundle chunking strategy evident
  • No background sync client trigger (offline requests never sync)
  • No periodic sync registration (no background updates)
  • No Network Information API usage (no adaptive behavior on slow networks)
  • Single caching strategy for all resources (not optimized)
  • No cache expiration config (unbounded cache growth)

Report Template

Generate the report in this exact format:

# PWA Audit Report

**URL:** [analyzed URL]
**Date:** [current date]
**Overall Score:** [X]/185 ([percentage]%) — Grade: [letter grade]

---

## Score Breakdown

| Category | Score | Status |
|----------|-------|--------|
| Manifest Compliance | X/20 | [status emoji] |
| Advanced Manifest | X/15 | [status emoji] |
| Service Worker & Caching | X/33 | [status emoji] |
| Offline Capability | X/19 | [status emoji] |
| Installability | X/13 | [status emoji] |
| Security | X/16 | [status emoji] |
| Performance Signals | X/17 | [status emoji] |
| UX & Accessibility | X/27 | [status emoji] |
| SEO & Discoverability | X/7 | [status emoji] |
| PWA Advanced | X/17 | [status emoji] |
| iOS Compatibility | X/1 | [status emoji] |

Status: Pass (80%+), Warn (50-79%), Fail (<50%)

---

## Critical Issues

[List any critical blockers that prevent PWA functionality]

---

## Warnings

[List important issues that should be addressed]

---

## Passed Checks

[Summarize what the PWA does well]

---

## Recommendations

### High Priority
1. [Most impactful fix]
2. [Second priority]

### Medium Priority
1. [Improvement]
2. [Enhancement]

### Quick Wins
- [Easy fix 1]
- [Easy fix 2]

---

## Resources

- [Web App Manifest | web.dev](https://web.dev/add-manifest/)
- [Service Workers | MDN](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)
- [PWA Checklist | web.dev](https://web.dev/pwa-checklist/)
- [Workbox | Google](https://developer.chrome.com/docs/workbox/)

---

*Generated by PWA Review Skill v5.4.0*

Error Handling

Manifest Not Found

  • Score Category 1 (Manifest Compliance) as 0/20
  • Score Category 2 (Advanced Manifest) as 0/13
  • Add CRITICAL issue: "No manifest.json found"
  • Continue with remaining categories

Service Worker Not Found

  • Score Category 3 (Service Worker & Caching) as 0/33
  • Score Category 4 (Offline Capability) as 0/19
  • Reduce Category 5 (Installability) by 2 points
  • Add CRITICAL issue: "No service worker registered"
  • Continue with remaining categories

CORS/Fetch Failures

  • Note which resource couldn't be fetched
  • Score affected categories as 0
  • Add WARNING: "Could not fetch [resource] - CORS or access issue"
  • Analyze whatever resources were successfully retrieved

Invalid JSON (Manifest)

  • Score manifest categories as 0
  • Add CRITICAL issue: "manifest.json contains invalid JSON"
  • Continue with HTML and SW analysis

iOS/Safari Limitations to Note

When generating the report, include these platform-specific notes if relevant:

Installation & Capabilities

  • iOS Safari: beforeinstallprompt event not supported (users must manually "Add to Home Screen")
  • iOS Safari: Push notifications require iOS 16.4+ and explicit user permission
  • iOS Safari: Storage limited to ~50MB (may be evicted under storage pressure)
  • iOS Safari: No persistent storage API
  • Safari: Service worker scope limitations more strict

Safe Area & Display (Critical for PWA Mode)

  • Notch/Dynamic Island: Without viewport-fit=cover in viewport meta, env(safe-area-inset-*) won't work
  • Fixed Headers: Must use padding-top: env(safe-area-inset-top) to avoid content being hidden behind notch
  • Fixed Bottom Elements: Must use padding-bottom: env(safe-area-inset-bottom) for home indicator area
  • Status Bar: apple-mobile-web-app-status-bar-style can be default, black, or black-translucent
  • PWA mode on iOS shows no browser chrome - safe area handling is essential

Touch Events & Interactions

  • onClick handlers may not fire reliably on some iOS versions in PWA mode
  • Add onTouchEnd as backup for critical buttons (install, update, submit actions)
  • Use touch-manipulation CSS to eliminate 300ms tap delay and prevent double-tap zoom
  • Use cursor: pointer CSS on interactive elements - iOS Safari requires this to recognize elements as clickable
  • Use -webkit-tap-highlight-color: transparent for clean visual feedback
  • Use -webkit-user-select: none on interactive elements to prevent text selection

Splash Screens

  • iOS requires <link rel="apple-touch-startup-image"> with media queries for each device size
  • Without splash screens, iOS shows blank white screen during PWA launch
  • Each iPhone/iPad dimension needs its own splash image (portrait and landscape)

Z-Index & Stacking Context (Critical)

  • backdrop-filter creates new stacking context: Headers with backdrop-blur or backdrop-filter create isolated stacking contexts in iOS Safari. Elements with higher z-index values may still appear BEHIND these elements.
  • Fix: Add transform: translate3d(0,0,0) to elements that need to appear above backdrop-filter elements. This forces GPU layer rendering and fixes stacking order.
  • Toast/notification components must have high z-index (e.g., z-[9999]) AND transform: translate3d(0,0,0) to appear above blurred headers
  • iOS Safari has stricter stacking context behavior than Chrome/Firefox

Example fix for notifications above blurred headers:

.notification {
  position: fixed;
  z-index: 9999;
  transform: translate3d(0,0,0); /* Forces GPU layer, fixes iOS stacking */
}

Example Usage

User: /pwa-review https://looknex.com

Claude will:

  1. Fetch https://looknex.com HTML
  2. Find manifest at /manifest.json
  3. Find SW at /sw.js
  4. Fetch and analyze both files
  5. Score across all 10 categories
  6. Generate detailed report with findings
</pwa-review>