--- title: "Progressive Web App (PWA) Guide" version: 3.8.40 lastUpdated: 2026-06-28 --- # Progressive Web App (PWA) Guide OmniRoute ships as a fully installable Progressive Web App. When you access the dashboard from any mobile browser — Android (Chrome) or iOS (Safari) — you can "Add to Home Screen" and get a native app-like experience with no app store required. ## What Is a PWA? A Progressive Web App turns the OmniRoute web dashboard into something that looks and feels like a native mobile app. Once installed, it: - Launches from your home screen with its own icon - Opens fullscreen — no browser address bar or tab UI - Works offline with a dedicated connectivity page - Caches static assets for faster loading - Supports both portrait and landscape orientations ## Installation ### Android (Chrome) 1. Open the OmniRoute dashboard in Chrome: `http://YOUR_IP:20128` 2. Chrome will show an **"Add OmniRoute to Home screen"** banner automatically, or: - Tap the **⋮** menu (three dots) → **"Add to Home screen"** or **"Install app"** 3. Confirm the prompt 4. OmniRoute appears on your home screen as a standalone app ### iOS (Safari) 1. Open the OmniRoute dashboard in Safari: `http://YOUR_IP:20128` 2. Tap the **Share** button (box with arrow) 3. Scroll down and tap **"Add to Home Screen"** 4. Name it (defaults to "OmniRoute") and tap **Add** 5. OmniRoute appears on your home screen with the app icon ### Desktop (Chrome / Edge) 1. Open the OmniRoute dashboard 2. Click the **install icon** in the address bar (or ⋮ → "Install OmniRoute...") 3. Confirm the prompt 4. OmniRoute opens as a standalone window — no tabs, no address bar ## Features ### Fullscreen Experience The manifest is configured with `display: "fullscreen"`, which means the installed app uses the entire screen — no browser chrome, no status bar overlap. This makes the dashboard feel truly native. ### Offline Support OmniRoute includes a service worker (`sw.js`) that provides intelligent caching: | Asset Type | Strategy | Behavior | | ------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------- | | **App Shell** | Cache-first | `/`, `/offline`, manifest, and icons are pre-cached on install | | **Static assets** (CSS, JS, images, fonts) | Network-first with cache fallback | Fetches fresh from the network; falls back to cache if offline | | **Next.js bundles** (`/_next/`) | Network-first with cache update | Fetches from network and updates cache; serves cached version if offline | | **Navigation requests** | Network-only with offline fallback | Always fetches from network; shows `/offline` page if network is unavailable | | **API routes** (`/api/`, `/a2a`, `/dashboard/endpoint`) | Bypass (never cached) | Always goes directly to the server — never intercepted by the service worker | ### Offline Page When the network is unavailable and a user navigates to a new page, the service worker serves a dedicated `/offline` page that: - Displays a clear **"Connectivity Issue"** message - Shows a live **online/offline status indicator** that updates in real time - Provides a **"Retry Connection"** button to reload when connectivity returns - Links to the **Status Page** for diagnostics ### App Icons OmniRoute provides icons optimized for each platform: | File | Size | Used By | | ---------------------- | ---------------- | ------------------------------------- | | `icon-512.png` | 512×512 | Android install prompt, splash screen | | `apple-touch-icon.png` | 180×180 | iOS home screen icon | | `icon-192.svg` | 192×192 (vector) | Android adaptive icon | | `apple-touch-icon.svg` | 180×180 (vector) | Apple fallback | | `favicon.svg` | Vector | Browser tabs | | `favicon.ico` | Multi-size | Legacy browsers | ### Automatic Registration The service worker is registered automatically via the `` component in the root layout. No user action is needed — the app becomes installable as soon as the browser detects the valid manifest and service worker. ## Technical Architecture ### Web App Manifest (`manifest.webmanifest`) Generated by Next.js via `src/app/manifest.ts`: ```json { "name": "OmniRoute", "short_name": "OmniRoute", "description": "OmniRoute is an AI gateway for multi-provider LLMs. One endpoint for all your AI providers.", "start_url": "/", "scope": "/", "display": "fullscreen", "orientation": "any", "background_color": "#0b0f1a", "theme_color": "#0b0f1a", "icons": [ { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }, { "src": "/apple-touch-icon.png", "sizes": "180x180", "type": "image/png" } ] } ``` ### Service Worker (`public/sw.js`) A vanilla service worker (no framework dependencies) with: - **Install phase**: Pre-caches the app shell (root, offline page, manifest, icons) - **Activate phase**: Cleans up old cache versions and claims all clients - **Fetch phase**: Intelligent routing based on request type (navigation, static asset, API) - **Cache versioning**: `omniroute-pwa-v2` — bump this to force a fresh cache on update ### Layout Metadata (`src/app/layout.tsx`) The root layout provides all the meta tags required for PWA compliance: - `manifest` link to `/manifest.webmanifest` - `apple-web-app-capable: true` for iOS standalone mode - `apple-web-app-status-bar-style: black-translucent` - `mobile-web-app-capable: yes` for Android Chrome - `theme-color: #0b0f1a` - `viewport-fit: cover` for edge-to-edge rendering ### Component: `PwaRegister` Located at `src/shared/components/PwaRegister.tsx`, this client component: 1. Runs on mount (client-side only) 2. Checks for `serviceWorker` support in the browser 3. Registers `/sw.js` silently (errors are swallowed to avoid blocking the app) 4. Renders nothing (`return null`) — it's a side-effect-only component ## Use With Termux (Android) When running OmniRoute on Android via Termux, the PWA works seamlessly: 1. Start OmniRoute in Termux: `npx omniroute` 2. Open Chrome on the same phone: `http://localhost:20128` 3. Install the PWA via "Add to Home Screen" 4. The PWA connects to the local Termux server — everything runs on-device This combination means your Android phone is both the **server** (Termux) and the **client** (PWA) — a complete self-contained AI gateway. ## Use From Other Devices Install the PWA on any device that has browser access to your OmniRoute server: - **Another phone/tablet**: Navigate to `http://PHONE_IP:20128` and install the PWA - **Laptop**: Open Chrome/Edge and install it as a desktop PWA - **Smart TV with browser**: Access the dashboard fullscreen ## Customization ### Instance Name The PWA title respects the **Instance Name** setting from `Dashboard → Settings`. If you rename your instance to "My AI Gateway", the installed PWA will show that name. ### Custom Favicon If you upload a custom favicon via `Dashboard → Settings`, the PWA icon on desktop will reflect the custom icon. Mobile home screen icons use the pre-built `icon-512.png` and `apple-touch-icon.png` files. ## Limitations - **No push notifications** — The service worker does not implement the Push API. Notifications are handled by the Electron app instead. - **No background sync** — Offline actions are not queued for replay. The PWA is primarily a dashboard viewer. - **iOS restrictions** — Safari on iOS does not support all PWA features (e.g., install prompts are manual, and background service workers are limited). - **Cache size** — The service worker caches static assets only. Large response payloads from `/api/` routes are never cached. - **Custom icons on mobile** — Changing the favicon in settings does not update the home screen icon on mobile (this requires regenerating the PWA icons). ## Files Reference | File | Purpose | | --------------------------------------- | ---------------------------------------------------------------- | | `src/app/manifest.ts` | Next.js manifest route (generates `manifest.webmanifest`) | | `public/sw.js` | Service worker with caching logic | | `src/shared/components/PwaRegister.tsx` | Client component that registers the service worker | | `src/app/offline/page.tsx` | Offline fallback page with live status indicator | | `src/app/layout.tsx` | Root layout with PWA metadata (apple-web-app, theme-color, etc.) | | `public/icon-512.png` | 512×512 PNG icon (Android, splash screen) | | `public/apple-touch-icon.png` | 180×180 PNG icon (iOS home screen) | | `public/icon-192.svg` | 192×192 SVG icon (Android adaptive) | | `public/apple-touch-icon.svg` | 180×180 SVG icon (Apple fallback) |