all repositories

russ/ap-bio AP Bio

Merge PR #12: web: offer to install the site as an app (claude/pwa-install-prompt-4c75d7)

merged by Russ T Fugalopened by Russ T Fugal9 files+1,977 −1831a77b312 merged here in total

AP Bio commit activity: 62 commits from 2026-06-21 through 2026-08-12.

description

Ports the install-prompt pattern from ~/code/sks/eclipse-calculator into this app's idiom — no new dependencies, no shadcn Sheet or sonner, everything drawn in the site's own nl-* primitives.

What lands

  • src/install/platform.ts — which install story the browser has. An iPad is told apart from a Mac by maxTouchPoints, since iPadOS 13+ sends a Macintosh user agent and a string match alone hands every iPad a Chromium flow it can never receive.
  • src/install/state.ts — the offer's memory, under apbio.install.v1. Not on the first load; a thirty-day snooze per dismissal; a hard stop after three.
  • src/install/deferredPrompt.ts — captures beforeinstallprompt from main.tsx before hydrateRoot. The version this was ported from registers that listener in a component effect, which is a coin flip: Chromium fires the event once, early, and routinely before React is up.
  • src/install/useInstallOffer.ts — the policy. describeOffer is pure and tested.
  • src/install/InstallOffer.tsx — the panel, mounted in the layout beside the shorts overlay. Native platforms get an Install button; iOS gets a disclosure that unfolds the Share → Add to Home Screen steps in place, so the steps stay on screen while the student reaches for the browser's own Share button.

Notes

  • Nothing is read during render, so the prerendered markup and the first client render agree — same discipline as useSavedClips.
  • The panel does not render while the shorts feed is open: it would be covered by the overlay but still focusable, which is a keyboard trap.
  • Firefox and desktop Safari get silence. Both can install this site, by menu paths that differ by version and that the page cannot verify it is describing correctly.

Verified

bun run check clean, 117 tests pass, full build + prerender + sw green. Both variants and the Escape dismiss were exercised in the browser at phone and desktop widths.

9 files changed

This view needs a browser with declarative shadow DOM: Chrome 111, Safari 16.4, or Firefox 123. Read the source instead.

This view needs a browser with declarative shadow DOM: Chrome 111, Safari 16.4, or Firefox 123. Read the source instead.

clone

$ git clone https://git.fugl.dev/russ/ap-bioanonymous, no account
$ git clone ssh://git.fugl.dev/russ/ap-bioneeds the bastion ProxyCommand