9 KiB
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 26-pwa-performance | 00 | execute | 1 |
|
true |
|
|
Purpose: Provides the upgraded SW that enables PERF-05 (cached load < 1s) and the test infrastructure for TDD in subsequent plans. Output: Upgraded sw.js, pwa.d.ts type declarations, 4 test stub files, idb + web-push installed.
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/26-pwa-performance/26-RESEARCH.md @.planning/phases/26-pwa-performance/26-UI-SPEC.md @ui/public/sw.js @ui/src/main.tsx Task 1: Install dependencies, create PWA types, and rewrite service worker ui/public/sw.js, ui/src/types/pwa.d.ts - ui/public/sw.js - ui/src/main.tsx - ui/public/site.webmanifest - .planning/phases/26-pwa-performance/26-RESEARCH.md 1. Install dependencies: - `pnpm --filter @paperclipai/ui add idb` - `pnpm --filter @paperclipai/server add web-push` - `pnpm --filter @paperclipai/server add --save-dev @types/web-push`-
Create
ui/src/types/pwa.d.tswith:BeforeInstallPromptEventinterface extendingEventwithprompt(): Promise<void>anduserChoice: Promise<{ outcome: "accepted" | "dismissed" }>properties- Global
WindowEventMapaugmentation addingbeforeinstallprompt: BeforeInstallPromptEvent
-
Rewrite
ui/public/sw.js— replace the entire file with a cache-first strategy:- Cache name:
"nexus-v1"(replaces"paperclip-v2") installevent: callself.skipWaiting(), pre-cache["/", "/index.html"]intonexus-v1activateevent: delete ALL caches whose name is NOT"nexus-v1"(this busts the oldpaperclip-v2cache), then callself.clients.claim()fetchevent handler: a. Ifurl.pathname.startsWith("/api")— return immediately (network-only, no interception) b. Ifrequest.mode === "navigate"— cache-first: trycaches.match("/"), fall back tofetch(request)c. If URL matches static extension regex/\.(js|css|woff2?|png|svg|ico|webmanifest)$/— cache-first: trycaches.match(request), on miss fetch and clone intonexus-v1cache, return response d. All other requests: pass through (no interception)pushevent handler: parseevent.data.json()for{ title, body, icon, data }, callself.registration.showNotification(title, { body, icon: icon || "/android-chrome-192x192.png", badge: "/favicon-32x32.png", data })notificationclickevent handler: close notification,clients.openWindow(event.notification.data?.url || "/")
- Cache name:
Do NOT modify ui/src/main.tsx — SW registration is already correct.
Do NOT modify ui/public/site.webmanifest — manifest is already complete (PWA-02, PWA-07 already satisfied).
grep -q "nexus-v1" ui/public/sw.js && grep -q "BeforeInstallPromptEvent" ui/src/types/pwa.d.ts && echo "PASS"
<acceptance_criteria>
- grep "nexus-v1" ui/public/sw.js returns the cache name
- grep "paperclip" ui/public/sw.js returns nothing (old name fully removed)
- grep "cache-first" ui/public/sw.js or the cache-first pattern (caches.match before fetch) is present for static assets
- grep "push" ui/public/sw.js shows push event listener
- grep "notificationclick" ui/public/sw.js shows notification click handler
- grep "BeforeInstallPromptEvent" ui/src/types/pwa.d.ts returns the type declaration
- pnpm --filter @paperclipai/ui exec -- node -e "require('idb')" succeeds (idb installed)
- pnpm --filter @paperclipai/server exec -- node -e "require('web-push')" succeeds (web-push installed)
</acceptance_criteria>
Service worker rewritten with cache-first strategy and nexus-v1 cache name. idb and web-push installed. PWA types declared.
-
ui/src/hooks/useOfflineQueue.test.ts:describe("useOfflineQueue")with:it.todo("enqueues message when offline")it.todo("flushes queue on online event")it.todo("stops flushing on first failed POST")it.todo("returns queued message count")
-
ui/src/hooks/useInstallPrompt.test.ts:describe("useInstallPrompt")with:it.todo("captures beforeinstallprompt event")it.todo("returns canInstall=true when event captured and not standalone")it.todo("returns canInstall=false when already installed (standalone)")it.todo("calls prompt() on the deferred event when promptInstall is called")
-
ui/src/hooks/usePushNotifications.test.ts:describe("usePushNotifications")with:it.todo("subscribes when permission is granted")it.todo("does not subscribe when permission is denied")it.todo("sends subscription to server via POST /api/push/subscribe")
-
ui/src/components/PullToRefresh.test.tsx:- Add
// @vitest-environment jsdompragma at top (mirrors SwipeToArchive.test.tsx pattern) describe("PullToRefresh")with:it.todo("calls onRefresh after drag exceeds 64px threshold")it.todo("does not trigger when scrollTop is not 0")it.todo("resets pull distance on touch end below threshold")
- Add
All test stubs should have minimal imports — no service mocks until implementation plans wire them up.
NOTE: No MobileNavBar.test.tsx is created — the existing MobileBottomNav in Layout.tsx already handles global mobile navigation. If tests are needed for MobileBottomNav, they would belong to a separate plan.
pnpm --filter @paperclipai/ui test --run useOfflineQueue useInstallPrompt usePushNotifications PullToRefresh 2>&1 | grep -E "todo|Tests" | head -10
<acceptance_criteria>
- All 4 test files exist at the specified paths
- Each file uses it.todo() not it.skip()
- PullToRefresh.test.tsx has // @vitest-environment jsdom at top
- pnpm --filter @paperclipai/ui test --run passes (todos are not failures)
</acceptance_criteria>
4 Wave 0 test stubs created covering PWA-01, PWA-03, PWA-06, PWA-08. All test files use it.todo() and pass vitest run.
<success_criteria> Service worker upgraded to cache-first with nexus-v1 cache. Dependencies installed. PWA types declared. All Wave 0 test stubs created and passing. </success_criteria>
After completion, create `.planning/phases/26-pwa-performance/26-00-SUMMARY.md`