Files
clawtap/docs/superpowers/specs/2026-03-26-pwa-optimization-design.md
kuannnn 42861ea7fa feat: ClawTap v0.1.0 — initial release
Multi-adapter mobile UI for AI coding assistants.
Supports Claude Code, Codex CLI, and Gemini CLI through one interface.

Features:
- Real-time bidirectional sync via tmux + WebSocket
- Cross-AI review (send one AI's output to another for review)
- Multi-review tabs with minimize/expand
- Push notifications (PWA) with smart session-aware filtering
- Three-channel event system (hooks, file watcher, pane monitor)
- Voice input, image paste, draft persistence
- Terminal-native design (JetBrains Mono, dark theme, pixel art claw)
- CLI with --adapter flag on every command
- Zero-overhead fire-and-forget hooks
2026-03-26 10:40:26 +08:00

6.1 KiB

PWA Optimization Design Spec

Date: 2026-03-26 Goal: Bring CodeTap's PWA to production-grade quality — proper viewport handling, splash screens, install prompts, SW updates, badge management, draft persistence, and navigation history.


Current State

CodeTap already has solid PWA foundations:

  • Service Worker with Workbox precaching (vite-plugin-pwa, injectManifest)
  • Web App Manifest (standalone, portrait, dark theme)
  • Push notifications with badge support
  • iOS meta tags (capable, black-translucent status bar)
  • Offline detection + OfflineView
  • overscroll-behavior: none, 16px inputs, h-dvh, safe-bottom

What's Missing

High Priority

1. Viewport & Safe Areas

Problem: Missing viewport-fit=cover. Only bottom safe area handled — notch/Dynamic Island area not accounted for.

Solution:

  • Add viewport-fit=cover to viewport meta tag in index.html
  • Add CSS for top safe area: headers get padding-top: env(safe-area-inset-top)
  • The standalone PWA mode on iOS with black-translucent status bar needs the content to extend behind the status bar — viewport-fit=cover enables this

Files: index.html, src/index.css

2. Splash Screen / Launch Images

Problem: White flash on app startup — no branded loading experience.

Solution:

  • Add apple-mobile-web-app-startup-image meta tags covering major iPhone sizes
  • Use media attribute with device-width, device-height, and device-pixel-ratio queries
  • Background: #09090b (matches theme), centered CodeTap mascot/logo
  • Generate splash images as data URIs or static PNGs in /public/splash/
  • Minimum coverage: iPhone SE, iPhone 14/15, iPhone 14/15 Pro Max, iPhone 16 Pro Max

Files: index.html, public/splash/ (new directory)

3. Android Install Prompt

Problem: No handling of beforeinstallprompt event — Android users never see install prompt.

Solution:

  • Listen for beforeinstallprompt in App.tsx, store the event in state
  • Show a dismissible install banner in SessionsView (below header)
  • Banner text: "Install CodeTap for a better experience" with Install/Dismiss buttons
  • On Install click: call event.prompt(), hide banner
  • On Dismiss: hide banner, store dismissal in localStorage so it doesn't reappear
  • After successful install (appinstalled event): hide banner permanently

Files: src/App.tsx, src/components/SessionsView.tsx

4. Service Worker Update Notification

Problem: SW updates silently — user doesn't know a new version is available.

Solution:

  • Listen for controllerchange on navigator.serviceWorker in App.tsx
  • When detected, show a toast at bottom: "New version available" with Refresh button
  • On click: window.location.reload()
  • Toast auto-dismisses after 10s but can be manually dismissed

Files: src/App.tsx

Medium Priority

5. Badge Clear on Focus

Problem: App badge persists even when user is actively looking at the app.

Solution:

  • In App.tsx, listen for visibilitychange event
  • When document.visibilityState === 'visible': call navigator.clearAppBadge() (with feature check)
  • This ensures badge is cleared whenever user switches back to the app

Files: src/App.tsx

6. Manifest Shortcuts

Problem: No quick actions from home screen long-press.

Solution:

  • Add shortcuts array to manifest in vite.config.ts:
    • "New Chat" — url: /?action=newchat, icon: chat-bubble-icon
  • In App.tsx, check for ?action=newchat param and navigate accordingly

Files: vite.config.ts, src/App.tsx

7. Input Draft Auto-Save

Problem: Typed text lost if app is backgrounded or crashes.

Solution:

  • In ShimmerInput: on every input change, debounce-save to localStorage with key codetap:draft:{sessionId}
  • On mount: restore draft from localStorage if present
  • On successful send or explicit clear: delete the draft
  • Debounce: 500ms to avoid excessive writes

Files: src/components/ShimmerInput.tsx

8. Manifest Screenshots

Problem: Missing screenshots for app stores and install prompts.

Solution:

  • Add screenshots array to manifest in vite.config.ts
  • Provide at minimum:
    • 1 narrow screenshot (phone, 1080x1920) — chat view
    • 1 wide screenshot (tablet/desktop, 1920x1080) — sessions view
  • Store in public/screenshots/

Files: vite.config.ts, public/screenshots/ (new directory)

Low Priority

9. Slow Network Detection

Problem: No feedback when on slow connection.

Solution:

  • Check navigator.connection?.effectiveType (with feature detection)
  • When 2g or slow-2g: show a subtle indicator in StatusBar ("Slow connection")
  • Re-check on change event of navigator.connection

Files: src/components/StatusBar.tsx

10. History API Navigation

Problem: Browser back gesture doesn't work — app uses sessionStorage for view state, no history stack.

Solution:

  • In App.tsx, use history.pushState() when navigating between views
  • Listen for popstate event to handle back navigation
  • Map each view to a history entry: sessions, chat/{sessionId}, settings, newchat/{cwd}
  • This enables iOS swipe-back gesture and Android back button in standalone mode

Files: src/App.tsx

11. OpenGraph Meta Tags

Problem: No social sharing metadata.

Solution:

  • Add to index.html:
    • og:title: "CodeTap"
    • og:description: "Use Claude Code from your phone"
    • og:image: link to a social card image
    • og:type: "website"
    • twitter:card: "summary"

Files: index.html


Design Principles

  1. Progressive enhancement — All PWA features use feature detection. App works fine without them.
  2. No new dependencies — Everything is native Web APIs or existing vite-plugin-pwa config.
  3. Minimal UI additions — Install banner and SW update toast are the only new UI elements.
  4. Respect user choice — Install prompt is dismissible and remembers dismissal.

Out of Scope

  • Full offline-first with background sync (current offline detection is sufficient)
  • Push notification permission prompt UI (current flow works)
  • Image compression before upload
  • Orientation lock via Screen Orientation API