Run the PWA device checklist and close each #249 child that passes #355
Description
Parent
#328. Related: #249, #197, #247, #248, #250, #251, #252, #253, #254, #255, #256, #258, #308, #309, #310, #312
What to build
The #249 PWA work is built and live on https://docs.plus. No child counts as shipped until it passes on a real device. Headless browsers cannot check a splash, a vibrate, an app badge, a share sheet, or a screen reader. This issue runs one checklist on real devices. Each child issue closes when all of its checks pass.
Acceptance criteria
- Every check in the table under "Agent brief" has a result: pass, fail, or not run, with the device and OS version.
- The results are posted as one comment on Deepen the installed PWA #249.
- Each Deepen the installed PWA #249 child whose checks all pass is closed, with a comment that names the device and OS version.
- Harden the offline document mirror: claim persistent storage, and surface a write failure #197 gets a comment with its row result. It stays open, because its storage-full check is not on this list.
- Each failed check has a comment on its child issue, with steps and a screen recording or screenshot. A failure that matches Hide the phone edit toolbar when the pad is read-only #308, A heading deep link puts the first Tab on a TOC row #309, Sheet focus trap: Tab escapes during the open tween, and the backdrop is an unnamed button #310 or A cold push click does not mark the notification read #312 goes on that issue instead.
- Deepen the installed PWA #249 stays open until every child is closed or has a filed failure.
Blocked by
None — can start now.
Agent brief
Type: HITL — a person with an iPhone, an Android phone and a desktop Chromium browser runs each check. They post the results on #249 and close the children that pass. The bounce alert row waits for #354; mark it "not run" until then.
Category: enhancement
Current behavior: The build is live. The production manifest serves share_target with action /receive, and the three iPhone splash images return 200 (checked 2026-09-28). The repo copy is apps/webapp/public/manifest.json. No real-device result is recorded on any #249 child.
Desired behavior: Each #249 child is either closed on a passed device check or carries a filed failure.
The checks, per device. "Issue" is where the result goes. A #249 child closes when all of its rows pass.
| Device | Check | Issue |
|---|---|---|
| iPhone with a 390, 393 or 430 pt wide screen (for example iPhone 14, 15, 16 or 16 Plus), Home Screen app | Remove the app, add it to the Home Screen again, then cold launch it. The splash image shows, not a blank white screen. The 16 Pro and 16 Pro Max have no splash image, so do not use them. | #255 |
| iPhone, Safari tab, signed in | On Home, the open keyboard collapses the Documents list and the Install control. The slug card stays. | #247 |
| iPhone, read-only pad | With Find open, no edit toolbar shows. | #250 (a failure outside Find goes on #308) |
| iPhone, editable pad | Type / on an empty line. The Slash menu opens and the keyboard stays up. |
#251 |
| iPhone | Export offers Save to Files. | #252 |
| iPhone | Chat Share opens the system share sheet with the chat URL. | #253 |
| iPhone, VoiceOver on | The pad skip link moves focus into the pad's one main landmark. Share, Make private and Sign out are dialogs named by their visible title. Focus stays inside the TOC drawer and the sheets, and returns to the opener on close. | #248 (a Tab leak during the open motion goes on #310) |
| Android, installed app | Hold a chat message for half a second. It buzzes once. A tap, a scroll, or a hold where the finger slides does not buzz. | #256 |
| Android, installed app | Share a .docx and a .md file into docs.plus, signed in. Each opens as a new pad with the file content. |
#253 |
| Android, installed app | Share a file into docs.plus while signed out. /receive shows Sign in. After sign-in, no pad is made from that file. |
#253 |
| Android, installed app | Type / on an empty line. The Slash menu opens and the keyboard stays up. |
#251 |
| Android, TalkBack on | Same results as the VoiceOver row. | #248 |
| Android, installed app | After the first edit in a pad, navigator.storage.persisted() returns true (remote DevTools console). |
#197 (comment only; do not close) |
| Desktop Chromium, installed app, a pad open | The app icon badge equals the bell count. Marking a notification read lowers it. Sign-out clears it. | #258 (a cold push click that does not mark read goes on #312) |
| Desktop Chromium | Export opens the save picker. Cancel shows no error and no toast. | #252 |
| Desktop Chromium, fresh profile | The first visit does not reload the page. After a later deploy, an open tab reloads once. | #249 |
| Push, any installed app | With pad A open, click a chat push for pad B. Pad B opens with that chat. | #249 |
| Any device, signed in with a test account | Click the bounce alert in the bell. Settings opens on the Notifications tab, not a pad named settings. Run after #354. |
#249 |
| macOS Safari | Cmd-f on a pad opens the pad Find bar, not Safari find. | #250 |
| macOS Safari | Home shows no Install control. | #247 |
| Firefox and Edge, desktop | Mod+Shift+K (Ctrl on Windows and Linux, Cmd on macOS) opens Command jump. In Firefox on Windows or Linux, the Web Console does not open. | #254 |
| Production database | No pad uses the slug receive (query below). |
#253 |
The slug check runs read-only on the production Prisma database:
select slug, "documentId", "createdAt", "deletedAt"
from "DocumentMetadata"
where lower(slug) = 'receive';Zero rows is a pass. One row means an old pad now sits behind the reserved route. Post the row on #253.
To create a bounce alert, use a test account only. A maintainer runs select public.record_email_bounce('<test account email>', 'hard'); in the Supabase SQL editor. That call also pauses the account's email notifications. Turn them back on in Settings → Notifications after the check.
Where to start: Only for writing a precise failure report. Splash: apps/webapp/src/pages/_document.tsx (apple-touch-startup-image). Badge: apps/webapp/src/utils/appBadge.ts. Vibrate: apps/webapp/src/components/chatroom/components/MessageCard/hooks/useLongPressInteraction.ts (navigator.vibrate). Home collapse: apps/webapp/src/components/pages/home/HomePage.tsx (HomeCollapseRegion). Persist: requestPersistentStorage in apps/webapp/src/hooks/useYdocAndProvider.ts. First-visit reload: controllerchange in apps/webapp/src/hooks/useServiceWorker.ts. Find: apps/webapp/src/components/TipTap/find/FindBar.tsx. Command jump: apps/webapp/src/components/commandJump/CommandJump.tsx. Inbound share: apps/webapp/public/service-worker.js and apps/webapp/src/pages/receive.tsx. Line numbers are hints as of 2026-09-28; the agent searches by symbol.
Rules that apply: apps/webapp/CLAUDE.md §Landing Page Shell And PWA (parked guards #257, #259, #260, #261 stay open). AGENTS.md §UI And Theme. Names follow CONTEXT.md (Slash menu, Command jump).
Verify: Run each row on https://docs.plus in light and dark theme where the row shows UI. Record device model, OS version and browser version for each result.
Out of scope
- Fixing a failed check. File or update the child issue, and fix it there.
- The known follow-ups Hide the phone edit toolbar when the pad is read-only #308, A heading deep link puts the first Tab on a TOC row #309, Sheet focus trap: Tab escapes during the open tween, and the backdrop is an unnamed button #310 and A cold push click does not mark the notification read #312. They own their own fixes.
- The Harden the offline document mirror: claim persistent storage, and surface a write failure #197 storage-full check. Harden the offline document mirror: claim persistent storage, and surface a write failure #197 owns it.
- Closing the parked cards Do not force the camera on the profile photo #257, Do not add folders #259, Do not add visit-based Recents #260 and Do not add a second pad window #261. They stay open as guards.
Activity