Files
clawtap/docs/superpowers/specs/2026-03-26-pwa-optimization-design.md
T
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

164 lines
6.1 KiB
Markdown

# 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