From 2406715b18b8451858714b80ab216319ffcf331e Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sat, 15 Aug 2026 14:48:50 -0700 Subject: [PATCH] Add PWA notes, mobile browse mode, mobile layout docs --- docs/design.md | 7 +++++++ docs/directory.md | 4 +++- docs/pwa.md | 21 +++++++++++++++++++++ docs/screenshots.md | 1 + tools/browse/main.go | 7 ++++++- 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 docs/pwa.md diff --git a/docs/design.md b/docs/design.md index 750a11c..2c97ec9 100644 --- a/docs/design.md +++ b/docs/design.md @@ -66,3 +66,10 @@ Original tile art (1254×1254 JPEGs for all nine classrooms and all nine grade t - List rows with right chevrons; hairline dividers; generous whitespace. - Detail pages break the white page with a full-width deep-teal band for family content. - Inline separators: "▶" chains grade to team to subteam; "·" dots separate contact fragments. + +## Responsive chrome + +- Phones are the primary target; the desktop layout is the adaptation, not the other way around. +- Narrow screens replace the sidebar with a brand-teal top bar (hamburger, page title, or back arrow + record name) and a bottom tab bar of icon-and-label items for the everyday sections. +- Content keeps one structure across widths: grids go from multi-column to two columns, detail blocks stack full-width, and the teal family band spans edge to edge. +- The status-bar area is part of the brand chrome (`viewport-fit=cover`, translucent status bar over teal — see `docs/pwa.md`). diff --git a/docs/directory.md b/docs/directory.md index d7bf9e5..95bd733 100644 --- a/docs/directory.md +++ b/docs/directory.md @@ -14,7 +14,9 @@ The directory ("Helios Who?") is the community's who's-who: students, parents, a ## Navigation -A persistent sidebar carries the app identity, the section list, and the signed-in user. Sections: +On wide screens a persistent sidebar carries the app identity, the section list, and the signed-in user. On phones — the primary way the community uses the app — the sidebar gives way to a dark-teal top bar and a bottom tab bar holding the six everyday sections (People, Classrooms, My Family, Staff, Map, Email List), with the rest behind a hamburger menu. The top bar shows the page title while browsing and becomes a back arrow plus the record's name on detail pages. Tab strips collapse to the first tabs plus "More ▾", people grids drop to two columns and gain a per-card overflow menu, detail pages stack their blocks full-width, and family-band member rows pick up photo thumbnails. Same structure throughout — only the chrome changes. + +Sections: ### People (home) diff --git a/docs/pwa.md b/docs/pwa.md new file mode 100644 index 0000000..5a18578 --- /dev/null +++ b/docs/pwa.md @@ -0,0 +1,21 @@ +# Installable web app + +The directory is used from phone home screens, so Heliosian ships as an installable web app (PWA), matching what the existing app does. These notes record how the existing app achieves it and what our server needs to serve. + +## How the existing app is wired + +- **Manifest** via ``: `name`/`short_name` ("Helios Who?"), `description`, `display: "standalone"`, `start_url` on the app's own domain, `theme_color` and `background_color` both brand teal `#014E54`, and icons — 16/32 favicons plus 192 and 512 PNGs, each in both `purpose: any` and `purpose: maskable` variants. +- **Head meta**: `viewport` with `viewport-fit=cover` (edge-to-edge under notches) and `user-scalable=no`; `apple-mobile-web-app-capable: yes`; `apple-mobile-web-app-status-bar-style: black-translucent`; a page-level `theme-color` set to the light surface color (`#F6F6F6`) — the manifest's teal governs install/launch chrome while the meta tracks in-app surface. +- **iOS extras**: an `apple-touch-icon`, and a large battery of `apple-touch-startup-image` links with device-specific media queries — pre-rendered splash screens (the logo lockup on teal) for every iPhone/iPad size, because iOS ignores the manifest for splash. +- **Service worker**: the shell assumes one may control the page (its boot script checks `navigator.serviceWorker.controller` to drive reload and offline-retry behavior), giving offline shell support and Android install quality. + +## What Heliosian serves + +- `manifest.webmanifest` from the binary: name, short name, `display: standalone`, `start_url: /`, theme and background color `#014E54`, icons 192 and 512 as `any` plus maskable variants (maskable art keeps the lockup inside the safe zone on a full-bleed teal square). +- Base template meta: `theme-color`, `viewport` including `viewport-fit=cover`, the two `apple-mobile-web-app-*` tags, and a 180px `apple-touch-icon`. +- HTTPS comes with Cloud Run; installability requires it. +- Splash screens for iOS are pre-rendered at the device-size matrix like the original; until that exists, launches show a plain background, which is acceptable. +- A service worker is optional for install on current Chromium and adds offline shell caching; if added, it stays minimal — cache the static shell, never cache directory data (community data must not persist on shared devices beyond the session's needs). +- `start_url` must resolve for a signed-out user by landing on the sign-in flow, then into the app. + +Icon and splash source files are derived from the brand assets (see `docs/design.md`). diff --git a/docs/screenshots.md b/docs/screenshots.md index 0c1c130..f8cd95d 100644 --- a/docs/screenshots.md +++ b/docs/screenshots.md @@ -50,6 +50,7 @@ Actions (at most one step's worth per invocation): - `-scroll ` — scroll vertically, negative for up - `-wait ` — block until this selector is visible before capturing - `-dump` — print the page HTML (for finding selectors) instead of writing a PNG +- `-mobile` — emulate a phone viewport (390×844, touch) instead of the desktop 1280×800; click coordinates still map 1:1 onto the screenshot The capture is the visible viewport, not the full page, so click coordinates read off a screenshot are directly usable. After an action that triggers cross-page navigation, always pass `-wait` with a selector expected on the destination page — the built-in settle delay is short, and without `-wait` the capture can race the navigation and show the previous page. The reported URL/title always reflect the final state; when a capture looks stale, re-run with no action to capture the current state. diff --git a/tools/browse/main.go b/tools/browse/main.go index fc58b70..5dddce3 100644 --- a/tools/browse/main.go +++ b/tools/browse/main.go @@ -108,6 +108,7 @@ func main() { typeText := flag.String("type", "", "insert text into the focused element") key := flag.String("key", "", "press a key: enter, tab, escape, backspace, or a literal character") wait := flag.String("wait", "", "css selector that must be visible before capturing") + mobile := flag.Bool("mobile", false, "emulate a phone viewport (390x844, touch) instead of desktop 1280x800") dump := flag.Bool("dump", false, "print page html instead of writing a screenshot") eval := flag.String("eval", "", "evaluate javascript in the page and print the json result instead of writing a screenshot") out := flag.String("out", "screenshots/browse.png", "output png path") @@ -123,7 +124,11 @@ func main() { ctx, cancelTimeout := context.WithTimeout(ctx, 15*time.Second) defer cancelTimeout() - actions := []chromedp.Action{chromedp.EmulateViewport(1280, 800)} + viewport := chromedp.EmulateViewport(1280, 800) + if *mobile { + viewport = chromedp.EmulateViewport(390, 844, chromedp.EmulateMobile) + } + actions := []chromedp.Action{viewport} if *nav != "" { actions = append(actions, chromedp.Navigate(*nav)) }