> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# PWA Setup & Configuration Guide

> Version: 2.1.0 Last Updated: 2026-03-30 Status: ✅ Fully Configured

**Version:** 2.1.0\
**Last Updated:** 2026-03-30\
**Status:** ✅ Fully Configured

Complete guide to Progressive Web App (PWA) setup, configuration, and optimization for the Encore Health OS Platform.

***

## Table of Contents

1. [Overview](#overview)
2. [Current Configuration](#current-configuration)
3. [Icon Setup](#icon-setup)
4. [Service Worker Configuration](#service-worker-configuration)
5. [Performance Optimization](#performance-optimization)
6. [Mobile Safe Area Support](#mobile-safe-area-support)
7. [Testing Checklist](#testing-checklist)
8. [Troubleshooting](#troubleshooting)
9. [References](#references)

***

## Overview

Encore Health OS is built as a Progressive Web App (PWA) with mobile-first responsive design, advanced caching strategies, and optimized build configuration for maximum performance.

**Key Features:**

* ✅ Auto-updating service worker
* ✅ Comprehensive Workbox caching strategies
* ✅ Raster icons generated from `public/favicon.svg` (Sharp + `png-to-ico`)
* ✅ Update notifications and offline support
* ✅ Mobile-first PWA features
* ✅ Unified icon system (Encore hex mark — aligned with `public/brand/encore-primary-dark.svg`)

**Related Documentation:**

* [Mobile Navigation Guide](./mobile-navigation-guide.md) - Mobile navigation patterns
* Development Documentation Index - Complete development guide index
* [Environment Variables](./ENVIRONMENT_VARIABLES.md) - Environment variable configuration for PWA

***

## Current Configuration

### Setup Status ✅

PWA setup is **fully configured** with icons generated from **`public/favicon.svg`** via Sharp and committed to `public/`.

* ✅ Auto-updating service worker
* ✅ Comprehensive Workbox caching strategies
* ✅ PNG + ICO outputs for favicon and install surfaces
* ✅ Update notifications and offline support
* ✅ Mobile-first PWA features
* ✅ Unified icon system (Encore hex mark — aligned with `public/brand/encore-primary-dark.svg`)

### Configuration Files

* **`vite.config.ts`** - VitePWA plugin configuration
* **`index.html`** - Viewport meta tag, apple-touch-icon links
* **`src/index.css`** - Safe area CSS custom properties
* **`src/platform/pwa/PwaUpdatePrompt.tsx`** - Update notification component

***

## Icon Setup

### Current icon set

| File                                 | Size             | Purpose                                                                                         |
| ------------------------------------ | ---------------- | ----------------------------------------------------------------------------------------------- |
| `favicon.svg`                        | 512×512 (vector) | Master artwork; matches `encore-primary-dark` geometry                                          |
| `favicon.png`                        | 32×32            | PNG favicon (`index.html`)                                                                      |
| `favicon.ico`                        | 16, 32, 48       | Multi-size ICO for browsers                                                                     |
| `pwa-64x64.png` … `pwa-512x512.png`  | various          | Manifest + `index.html`                                                                         |
| `pwa-128x128.png`, `pwa-256x256.png` | 128, 256         | Manifest (`vite.config.ts`)                                                                     |
| `maskable-icon-512x512.png`          | 512×512          | Android adaptive (purpose: `maskable`); logo drawn at \~410×410 centered (\~20% edge safe zone) |
| `apple-touch-icon-180x180.png`       | 180×180          | iOS home screen                                                                                 |

### Source asset

* **`public/favicon.svg`** — Master Encore hex mark (512×512 viewBox, rounded square). Design source: **`public/brand/encore-primary-dark.svg`** (scale and rounding applied for app-icon use).

### Icon generation

From the repository root:

```bash theme={null}
# PWA PNGs, maskable 512, favicon.png (32), favicon.ico (16/32/48)
node scripts/generate-pwa-icons.mjs

# iOS apple-touch icon (180×180) from the same SVG
npx tsx scripts/utils/generate-apple-touch-icon.ts
```

Dependencies: **sharp** (rasterization), **png-to-ico** (ICO file). Regenerate and commit outputs under `public/` after changing `favicon.svg`. Bump the `?v=` query on favicon links in `index.html` if browsers cache aggressively.

**Maskable icon:** `maskable-icon-512x512.png` uses a 512×512 canvas with the SVG rasterized at 410×410 and composited centered, reserving roughly a 20% edge safe zone for Android adaptive icon masks (see [Adaptive icons](https://developer.android.com/develop/ui/views/launch/icon_design_adaptive)).

### Manifest Configuration

The PWA manifest is configured in `vite.config.ts` using VitePWA plugin:

See **`vite.config.ts`** for the live `VitePWA` block. It includes `favicon.ico`, `favicon.png`, `apple-touch-icon-180x180.png`, and manifest icons (`pwa-64x64` through `pwa-512x512`, plus `maskable-icon-512x512.png`). `theme_color` / `background_color` use Encore navy (`#0D2140`).

**Key Points:**

* `registerType: "autoUpdate"` - Service worker updates automatically
* Separate `any` and `maskable` icons for best platform compatibility
* iOS home screen icon specified in `index.html` with `<link rel="apple-touch-icon">`
* `background_color` matches `theme_color` for consistent branding

### HTML References

**Update `index.html`:**

`index.html` links `favicon.svg`, `favicon.ico`, `favicon.png`, PWA PNG sizes, and `apple-touch-icon-180x180.png` with a cache-bust query (e.g. `?v=5`). Keep those in sync when regenerating assets.

### Icon regeneration

```bash theme={null}
node scripts/generate-pwa-icons.mjs
npx tsx scripts/utils/generate-apple-touch-icon.ts
```

Commit updated binaries under `public/` (and bump `?v=` in `index.html` when needed).

***

## Service Worker Configuration

### Auto-Registration (VitePWA)

Encore Health OS uses VitePWA for automatic service worker registration. No manual registration code needed.

**Current approach:**

* VitePWA handles registration automatically
* Service worker updates via `useRegisterSW()` hook from `virtual:pwa-register/react`

### Update Notifications

**Component:** `src/platform/pwa/PwaUpdatePrompt.tsx`

Uses `useRegisterSW()` hook to detect when a new service worker is available and shows a toast notification:

```typescript theme={null}
import { useRegisterSW } from 'virtual:pwa-register/react';
import { toast } from 'sonner';

export function PwaUpdatePrompt() {
  const {
    needRefresh: [needRefresh, setNeedRefresh],
    updateServiceWorker,
  } = useRegisterSW();

  useEffect(() => {
    if (needRefresh) {
      toast('New version available!', {
        description: 'Click update to get the latest features.',
        action: {
          label: 'Update',
          onClick: () => updateServiceWorker(true),
        },
        duration: Infinity,
      });
    }
  }, [needRefresh, updateServiceWorker]);

  return null;
}
```

**Integration:** Component added to `src/App.tsx` for app-wide update detection.

***

## Performance Optimization

### Vite Build Configuration

The project uses manual chunk splitting for optimal caching and load performance:

**Vendor Chunks:**

* `vendor-react`: React, ReactDOM, React Router (\~150KB)
* `vendor-radix`: Radix UI components (\~100KB)
* `vendor-query`: TanStack Query (\~40KB)
* `vendor-supabase`: Supabase client (\~80KB)
* `vendor-charts`: Recharts, D3 (\~200KB)
* `vendor-forms`: React Hook Form, Zod (\~50KB)
* `vendor-pdf`: PDF.js libraries (\~400KB)
* `vendor-dnd`: DnD Kit (\~50KB)
* `vendor-flow`: XY Flow (\~150KB)

**Core Module Chunks:**

* `core-hr`: HR module
* `core-fa`: Finance module
* `core-fw`: Forms/Workflow module
* `core-rh`: Recovery Housing module
* `core-gr`: Governance module
* `core-fm`: Facilities module
* `core-cl`: Clinical module

**Platform Module Chunks:**

* `platform-documents`: Document management
* `platform-reports`: Reporting engine
* `platform-forms`: Form builder
* `platform-notifications`: Notification system

**Benefits:**

* Users only download chunks they need
* Vendor chunks cached long-term (rarely change)
* Core modules cached per-domain
* Better cache invalidation (only changed chunks re-downloaded)
* Initial bundle size reduced by 60-70%

### Workbox Caching Strategies

**CacheFirst (Long-lived assets):**

* Google Fonts API cache (1 year, 10 entries)
* Google Fonts webfonts (1 year, 20 entries)
* Images (30 days, 100 entries) - `.png`, `.jpg`, `.jpeg`, `.svg`, `.gif`, `.webp`

**NetworkFirst (Dynamic data):**

* Supabase API calls (5 minute cache, 10s timeout, 50 entries)

**Navigation Preload:**

* Enabled for faster page loads
* Preloads navigation requests while service worker starts

### Bundle Analysis

To analyze bundle size and chunk distribution:

```bash theme={null}
npm run build
npx vite-bundle-visualizer
```

This helps identify large dependencies and optimization opportunities.

***

## Mobile Safe Area Support

### CSS Custom Properties

Safe area insets are defined in `src/index.css` using `env()` function:

```css theme={null}
:root {
  /* Safe Area Insets for Modern Mobile Devices */
  --safe-area-inset-top: env(safe-area-inset-top, 0px);
  --safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);
  --safe-area-inset-left: env(safe-area-inset-left, 0px);
  --safe-area-inset-right: env(safe-area-inset-right, 0px);

  /* Mobile Navigation Heights (see src/index.css for live tokens) */
  --mobile-header-height: 48px;
  --mobile-header-context-height: 32px; /* second row when visible */
  --mobile-header-switcher-height: 0px; /* legacy; main offset uses conditional context row */
  --mobile-nav-height: 64px;
}
```

### Utility Classes

Convenience classes for applying safe area padding:

```css theme={null}
@layer utilities {
  .safe-area-top { padding-top: var(--safe-area-inset-top); }
  .safe-area-bottom { padding-bottom: var(--safe-area-inset-bottom); }
  .safe-area-left { padding-left: var(--safe-area-inset-left); }
  .safe-area-right { padding-right: var(--safe-area-inset-right); }
}
```

### Component Implementation

**MobileHeader.tsx:**

```typescript theme={null}
<header className="... safe-area-top">
  <div className="h-16 flex items-center justify-between px-4">
    {/* Content pushed below notch */}
  </div>
</header>
```

**MobileNav.tsx:**

```typescript theme={null}
<nav className="... safe-area-bottom">
  <div className="flex items-center justify-around h-16 px-2">
    {/* Content pushed above home indicator */}
  </div>
</nav>
```

**ResponsiveNav.tsx (pattern):** `padding-top` on mobile `main` must match whether the second header row is rendered. The app uses `shouldShowMobileHeaderContextRow` so `main` adds `var(--mobile-header-context-height)` only when that row is visible (see source for the exact `calc(...)` classes).

### Viewport Meta Tag

Required for safe area insets to work:

```html theme={null}
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
```

**Key:** `viewport-fit=cover` tells the browser to extend content into safe areas.

***

## PWA Shortcuts and Categories

The PWA manifest includes shortcuts for quick access to key features:

```typescript theme={null}
shortcuts: [
  {
    name: "Dashboard",
    short_name: "Dashboard",
    url: "/",
    icons: [{ src: "/pwa-192x192.png", sizes: "192x192" }]
  },
  {
    name: "Forms",
    short_name: "Forms",
    url: "/fw/forms",
    icons: [{ src: "/pwa-192x192.png", sizes: "192x192" }]
  },
  {
    name: "Census",
    short_name: "Census",
    url: "/rh/census",
    icons: [{ src: "/pwa-192x192.png", sizes: "192x192" }]
  }
]
```

These shortcuts appear in the PWA install prompt and app launcher on supported devices.

### App Categories

The manifest specifies categories for better app store classification:

* `business`
* `productivity`
* `medical`

***

## Key Features

### Offline Capability

* Service worker caches forms and submissions for offline access
* Background sync queues form submissions when offline
* Graceful degradation for features requiring connectivity

### Mobile Optimization

* Touch-friendly UI (44×44px minimum touch targets)
* Safe area support for devices with notches, Dynamic Island, home indicators
* Responsive breakpoints: Mobile (320px) → Tablet (768px, 1024px) → Desktop (1280px+)
* Native-like interactions (swipe gestures, bottom navigation)
* Optimized for portrait orientation with landscape support

### Installation

* Installable as standalone app on iOS, Android, and desktop
* Real PWA icons (not placeholders)
* Custom install prompt for better UX (planned)
* App update notifications with auto-refresh option

***

## Technical Stack

* **Vite Plugin PWA**: Build-time service worker generation
* **Workbox**: Runtime caching strategies
* **Service Worker**: Background sync, push notifications (future)
* **React Hook**: `virtual:pwa-register/react` for update detection

***

## Testing Checklist

### PWA Functionality

* [ ] Service worker registers correctly
* [ ] Offline mode works
* [ ] Update prompt appears when new version available
* [ ] Icons display correctly on home screen
* [ ] Manifest validates (use Lighthouse)

### Icon Testing

* [ ] Icons appear in browser tab
* [ ] Icons appear in PWA install prompt
* [ ] Icons appear on iOS home screen
* [ ] Maskable icons work on Android
* [ ] Icons scale correctly at all sizes

### Mobile Testing

**Device Emulation:**

1. Use browser DevTools device emulation
2. Select devices with notches (iPhone 14 Pro, Pixel 7) to test safe areas
3. Test both portrait and landscape orientations

**Physical Devices:**

1. Test on actual mobile devices via network URL
2. Verify safe area rendering on notched devices
3. Test install-to-home-screen flow

**Offline Testing:**

1. DevTools → Network → Offline
2. Verify forms still render and submissions queue
3. Go back online and verify sync

### Performance Testing

* [ ] Lighthouse PWA score: 90+
* [ ] First Contentful Paint: \<2s
* [ ] Time to Interactive: \<3.5s on 3G
* [ ] Offline forms fully functional
* [ ] Safe area CSS uses hardware-optimized env() (no JS overhead)

***

## Performance Targets

* Lighthouse PWA score: 90+
* First Contentful Paint: \<2s
* Time to Interactive: \<3.5s on 3G
* Offline forms fully functional
* Safe area CSS uses hardware-optimized env() (no JS overhead)

***

## Troubleshooting

### Icons Not Displaying

**Problem:** Icons don't appear in browser tab or PWA install prompt

**Solutions:**

1. Verify icon files exist in `public/` directory
2. Check `vite.config.ts` icon paths are correct
3. Clear browser cache and service worker
4. Regenerate icons using the process above
5. Check browser console for 404 errors

### Service Worker Not Registering

**Problem:** Service worker doesn't register or update

**Solutions:**

1. Check browser console for errors
2. Verify VitePWA plugin is configured in `vite.config.ts`
3. Clear service worker cache in DevTools → Application → Service Workers
4. Check `registerType` is set to `"autoUpdate"`

### Safe Area Insets Not Working

**Problem:** Content hidden behind notch or home indicator

**Solutions:**

1. Verify viewport meta tag includes `viewport-fit=cover`
2. Check CSS uses `env(safe-area-inset-*)` correctly
3. Test on actual device (emulation may not show correctly)
4. Verify safe area classes are applied to correct elements

### Offline Mode Not Working

**Problem:** App doesn't work offline

**Solutions:**

1. Verify service worker is registered
2. Check Workbox caching strategies are configured
3. Test in DevTools → Network → Offline
4. Check service worker cache in DevTools → Application → Cache Storage

### Update Notification Not Showing

**Problem:** Users don't see update notifications

**Solutions:**

1. Verify `PwaUpdatePrompt` component is in `App.tsx`
2. Check `useRegisterSW()` hook is working
3. Test by making a code change and rebuilding
4. Check browser console for errors

***

## References

* [vite-plugin-pwa Documentation](https://vite-pwa-org.netlify.app/)
* [PWA Assets Generator](https://vite-pwa-org.netlify.app/assets-generator/)
* [Web App Manifest Spec](https://www.w3.org/TR/appmanifest/)
* [Workbox Documentation](https://developers.google.com/web/tools/workbox)
* [Safe Area Insets](https://developer.apple.com/design/human-interface-guidelines/layout)
* [Mobile Navigation Guide](./mobile-navigation-guide.md)

***

**Maintained By:** Platform Team\
**Status:** ✅ Ready for Production | ✅ Unified Icon System Active (Gold Compass on Dark Blue)
