--- phase: 08-mobile-pwa plan: 01 type: execute wave: 1 depends_on: [] files_modified: - packages/portal/package.json - packages/portal/next.config.ts - packages/portal/app/manifest.ts - packages/portal/app/sw.ts - packages/portal/app/layout.tsx - packages/portal/app/(dashboard)/layout.tsx - packages/portal/components/mobile-nav.tsx - packages/portal/components/mobile-more-sheet.tsx - packages/portal/components/sw-register.tsx - packages/portal/components/offline-banner.tsx - packages/portal/lib/use-offline.ts - packages/portal/public/icon-192.png - packages/portal/public/icon-512.png - packages/portal/public/icon-maskable-192.png - packages/portal/public/apple-touch-icon.png - packages/portal/public/badge-72.png - packages/portal/messages/en.json - packages/portal/messages/es.json - packages/portal/messages/pt.json autonomous: true requirements: - MOB-01 - MOB-02 - MOB-04 must_haves: truths: - "Desktop sidebar is hidden on screens < 768px; bottom tab bar appears instead" - "Bottom tab bar has 5 items: Dashboard, Employees, Chat, Usage, More" - "More sheet opens with Billing, API Keys, Users, Platform, Settings, Sign Out (RBAC-filtered)" - "Main content has bottom padding on mobile to clear the tab bar" - "Portal is installable as a PWA with manifest, icons, and service worker" - "Offline banner appears when network is lost" - "All existing pages remain functional on desktop (no regression)" artifacts: - path: "packages/portal/components/mobile-nav.tsx" provides: "Bottom tab bar navigation for mobile" exports: ["MobileNav"] - path: "packages/portal/components/mobile-more-sheet.tsx" provides: "Bottom sheet for secondary nav items" exports: ["MobileMoreSheet"] - path: "packages/portal/app/manifest.ts" provides: "PWA manifest with K monogram icons" exports: ["default"] - path: "packages/portal/app/sw.ts" provides: "Service worker with Serwist precaching" - path: "packages/portal/components/sw-register.tsx" provides: "Service worker registration client component" exports: ["ServiceWorkerRegistration"] - path: "packages/portal/components/offline-banner.tsx" provides: "Offline status indicator" exports: ["OfflineBanner"] key_links: - from: "packages/portal/app/(dashboard)/layout.tsx" to: "packages/portal/components/mobile-nav.tsx" via: "conditional render with hidden md:flex / md:hidden" pattern: "MobileNav.*md:hidden" - from: "packages/portal/next.config.ts" to: "packages/portal/app/sw.ts" via: "withSerwist wrapper generates public/sw.js from app/sw.ts" pattern: "withSerwist" - from: "packages/portal/app/layout.tsx" to: "packages/portal/components/sw-register.tsx" via: "mounted in body for service worker registration" pattern: "ServiceWorkerRegistration" --- Responsive mobile layout foundation and PWA infrastructure. Desktop sidebar becomes a bottom tab bar on mobile, PWA manifest and service worker enable installability, and offline detection provides status feedback. Purpose: This is the structural foundation that all other mobile plans build on. The layout split (sidebar vs tab bar) affects every page, and PWA infrastructure (manifest + service worker) is required before push notifications or offline caching can work. Output: Mobile-responsive dashboard layout, bottom tab bar with More sheet, PWA manifest with K monogram icons, Serwist service worker, offline banner component. @/home/adelorenzo/.claude/get-shit-done/workflows/execute-plan.md @/home/adelorenzo/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/08-mobile-pwa/08-CONTEXT.md @.planning/phases/08-mobile-pwa/08-RESEARCH.md From packages/portal/components/nav.tsx: ```typescript type NavItem = { href: string; label: string; icon: React.ElementType; allowedRoles?: string[]; }; // Nav items array (lines 43-53): // Dashboard, Tenants (platform_admin), Employees, Chat, Usage, // Billing (admin+), API Keys (admin+), Users (admin+), Platform (platform_admin) // Role filtering: visibleItems = navItems.filter(item => !item.allowedRoles || item.allowedRoles.includes(role)) ``` From packages/portal/app/(dashboard)/layout.tsx: ```typescript // Current layout: flex min-h-screen,