# Phase 8: Mobile + PWA - Research **Researched:** 2026-03-25 **Domain:** Responsive layout, PWA (manifest + service worker), push notifications, mobile UX patterns **Confidence:** HIGH --- ## User Constraints (from CONTEXT.md) ### Locked Decisions - Dual navigation: bottom tab bar (5 items) for main nav + hamburger/"More" menu for secondary items - Bottom tab bar items: Dashboard, Employees, Chat, Usage, More - "More" menu contains: Billing, API Keys, Users, Platform, Settings, Sign Out - Breakpoint: 768px (md) — tablets and below get mobile layout, desktop keeps the sidebar - RBAC still applies — operators don't see admin-only items in either nav or "More" - Chat: conversation list → full-screen chat pattern (like WhatsApp/iMessage) - Top bar in full-screen chat: back arrow + agent name + agent avatar - Message input: fixed at bottom, pushes content up when virtual keyboard opens - App icon: bold "K" monogram on gradient mesh background (matching login page aesthetic) - Splash screen: same gradient + K branding - Install prompt: smart banner on second visit — not intrusive - Offline: app shell cached + recently viewed pages. Chat history viewable offline. - Offline banner: shows "You're offline" indicator when disconnected - Message queue: new messages queue locally until reconnection, then send automatically - Push notifications: MUST HAVE — users get notified when AI Employee responds ### Claude's Discretion - "More" menu exact style (bottom sheet vs full-screen overlay vs side drawer) - Service worker caching strategy (workbox, serwist, or manual) - Push notification provider (Web Push API, Firebase Cloud Messaging, or OneSignal) - Touch gesture handling (swipe-to-go-back, pull-to-refresh, etc.) - Tablet-specific layout adjustments (if any beyond the breakpoint) - PWA manifest theme color and background color - How to handle the language switcher on mobile ### Deferred Ideas (OUT OF SCOPE) None — discussion stayed within phase scope --- ## Phase Requirements | ID | Description | Research Support | |----|-------------|-----------------| | MOB-01 | All portal pages render correctly and are usable on mobile (320px–480px) and tablet (768px–1024px) screens | Tailwind v4 `md:` responsive utilities + layout restructuring | | MOB-02 | Sidebar collapses to bottom tab bar on mobile with smooth open/close animation | New `MobileNav` component using `md:hidden` / `hidden md:flex` split; bottom tab bar pattern | | MOB-03 | Chat interface is fully functional on mobile — send messages, see streaming responses, scroll history | Mobile full-screen chat mode + Visual Viewport API for keyboard handling | | MOB-04 | Portal installable as a PWA with app icon, splash screen, and service worker for offline shell caching | `app/manifest.ts` + `@serwist/next` + icon assets in `public/` | | MOB-05 | Push notifications for new messages when PWA is installed | `web-push` library + VAPID keys + push subscription stored in DB + service worker push handler | | MOB-06 | All touch interactions feel native — no hover-dependent UI that breaks on touch devices | Tailwind v4 already scopes `hover:` inside `@media (hover: hover)` — verify no manual hover-dependent flows | --- ## Summary Phase 8 converts the existing desktop-only portal (fixed 260px sidebar, two-column chat layout) into a fully responsive mobile experience and adds PWA installability with offline support and push notifications. The portal is built on Next.js 16 App Router with Tailwind v4, which provides nearly all the responsive and touch-safe primitives needed. The responsive work is primarily additive CSS via Tailwind's `md:` breakpoint — hide the sidebar on mobile, add a bottom tab bar below it, restructure pages that use horizontal layouts into stacked vertical layouts. The chat page requires logic-level changes to implement the WhatsApp-style full-screen conversation toggle on mobile. PWA infrastructure uses three coordinated pieces: `app/manifest.ts` (built into Next.js 16), Serwist (`@serwist/next`) for service worker and offline caching, and the native Web Push API with the `web-push` npm library for push notifications. The `output: "standalone"` config is already set in `next.config.ts`, making the app PWA-compatible at the infrastructure level. **Primary recommendation:** Use `@serwist/next` for service worker and caching. Use `web-push` + VAPID for push notifications (no third-party dependency). Handle the iOS keyboard problem with the Visual Viewport API. Recommend bottom sheet for the "More" menu. --- ## Standard Stack ### Core | Library | Version | Purpose | Why Standard | |---------|---------|---------|--------------| | `@serwist/next` | ^9.x | Service worker generation, offline caching, precaching | Official Next.js recommendation; Workbox fork maintained actively; Turbopack-incompatible (use `--webpack` flag) | | `web-push` | ^3.6.x | VAPID key generation, push notification sending from server | Official Web Push Protocol implementation; no third-party service needed | | `idb` | ^8.x | IndexedDB wrapper for offline message queue | Async-native, promise-based; avoids localStorage limits for queued messages | ### Supporting | Library | Version | Purpose | When to Use | |---------|---------|---------|-------------| | `lucide-react` | already installed | Back arrow, hamburger, More icons for mobile nav | Already in project | | `@base-ui/react` | already installed | Bottom sheet / drawer for "More" menu | Already in project; Dialog + Sheet variants available | ### Alternatives Considered | Instead of | Could Use | Tradeoff | |------------|-----------|----------| | `@serwist/next` | `@ducanh2912/next-pwa` | Both are next-pwa successors; Serwist has official Next.js docs recommendation | | `web-push` | Firebase Cloud Messaging / OneSignal | web-push has no vendor lock-in; FCM/OneSignal add dashboard overhead; web-push is simpler for a single-tenant push flow | | Visual Viewport API (JS) | `dvh` CSS units | dvh is simpler but Safari iOS support for keyboard-aware dvh is inconsistent; Visual Viewport API is more reliable | **Installation:** ```bash npm install @serwist/next serwist web-push idb npm install -D @types/web-push ``` --- ## Architecture Patterns ### Recommended Project Structure (additions only) ``` packages/portal/ ├── app/ │ ├── manifest.ts # PWA manifest (Next.js built-in) │ ├── sw.ts # Serwist service worker source │ └── (dashboard)/ │ └── layout.tsx # Add mobile nav alongside existing sidebar ├── components/ │ ├── mobile-nav.tsx # Bottom tab bar — new │ ├── mobile-more-sheet.tsx # "More" bottom sheet — new │ ├── mobile-chat-header.tsx # Back arrow + agent name header — new │ ├── offline-banner.tsx # "You're offline" indicator — new │ └── install-prompt.tsx # Second-visit install banner — new ├── lib/ │ ├── push-subscriptions.ts # Server: store/retrieve push subscriptions │ ├── message-queue.ts # Client: IndexedDB queue for offline messages │ └── use-offline.ts # Client hook: online/offline state ├── public/ │ ├── sw.js # Serwist output (generated, do not edit) │ ├── icon-192.png # K monogram on gradient, 192×192 │ ├── icon-512.png # K monogram on gradient, 512×512 │ ├── icon-maskable-192.png # Maskable variant (safe-zone K) │ └── apple-touch-icon.png # iOS home screen icon, 180×180 └── next.config.ts # Add withSerwist wrapper ``` ### Pattern 1: Layout Split (Desktop sidebar vs Mobile bottom bar) **What:** The `DashboardLayout` renders the `