Files
command-center/agent/managed-skills/screenshot-walkthrough-in-static-docs/SKILL.md
T

37 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: screenshot-walkthrough-in-static-docs
description: "Embed a real-browser user-flow walkthrough (screenshots as data URIs) into a single-file zero-JS static docs page; includes the selector laws, cookie isolation, and secret-gate proof earned driving franksign's full demo."
---
name: screenshot-walkthrough-in-static-docs
description: "Embed a real-browser user-flow walkthrough (screenshots as data URIs) into a single-file zero-JS static docs page."
# Screenshot walkthroughs in a single-file static guide
Friction-earned 2026-10-21 on `dank/franksign` `guide/index.html` §13: 19 un-retouched captures of every user flow (signup → studio → template → send → sign → freeze → signed PDF → claim shelf → void → 410 door), embedded as data URIs, guide still single file, zero JS.
## Recipe (end to end)
1. **Boot the prod-shaped stack** on a non-collision port (`PORT=3210`; e2e seams squat :3100, demos :3000). Kill it before running any test gate.
2. **Walk flows as distinct identities sequentially** — the managed browser shares ONE cookie jar across tabs. Between roles: `tab.clearCookies()` then `tab.reload()` **on the app's origin, never on `about:blank`** (domain-scoped clear on about:blank clears nothing and the previous identity's session silently survives — you'll screenshot the admin where you meant the signer).
3. Fresh per-checkout demo state is fine; re-running flows with new identities leaves harmless history that actually *helps* later shots (roster with completed + pending + voided rows).
4. **Selectors**: prefer `role/textbox[name="Label *"]` / `role/button[name="Sign"]` / `testid/…`. Forms render required markers INTO the label text (`Email *`) — `label="Email"` misses; `text/…` clicks may silently no-op where `role/button[...]` works. Snapshot once per screen (`tab.ariaSnapshot(undefined,{compact:true,interactive:true})`) instead of guessing.
5. **Screenshot to disk** (path option silently ignored — see `browser-screenshot-disk-and-cookies`): `tab.run(async ({page}, p) => { const r = await page.screenshot({encoding:"base64", type:"png"}); await Bun.write(p, Buffer.from(typeof r === "string" ? r : r.data, "base64")); }, { args: [path] })` — this variant returns a bare string, not `{data}`; handle both.
6. **Shrink before embedding**: `for f in *.png; do magick "$f" -resize 1000x "$f"; done` → 17–83 kB each; 19 shots ≈ 800 kB raw, ~1.1 MB final guide.
7. **Non-browser payoff shots**: rasterize artifacts the flow produces (e.g. signed PDF) with `pdftoppm -png -r 90` + resize — the deterministic-output image is the best single screenshot of a PDF pipeline.
8. **Assembly**: write the section HTML with `__IMG:name__` placeholders via the write tool; a one-shot node script replaces tokens with `data:image/png;base64,…` and splices before `<footer>`. Never paste base64 through the edit tool.
9. Update nav + add a pointer paragraph from the prose-journeys section to the walkthrough section.
## Verify
Serve the dir (`python3 -m http.server`), open, assert via one evaluate: `img` count == captured, `failed == 0` (`complete && naturalWidth>0`), and every `href^="#"` resolves to an id. Screenshot the section top + a mid scroll. Then kill the stack BEFORE the gate.
## Secret gate vs data URIs
A base64 wall trips shape patterns (`AKIA/ASIA[A-Z0-9]{16}` etc.) via case-insensitive grep at law-of-large-numbers rates. Prove noise, don't just override: `git diff --cached | grep -oEi '<patterns>' | sort -u` — hits that are substrings of PNG streams (mixed-case `AkIa…`, random tails) are image bytes. Then use the hook's documented deliberate override (`ALLOW_SECRETS=1 git commit`) and record the proof in the commit body. Confirm no real credential is visible in any shot first (password fields render masked; note demo tokens in captions are dev-DB throwaways).
## Voice/law notes
- Captions must state what the demo fakes (no SMTP → "link travels by copy-paste") and that captures are un-retouched with real demo values.
- The walkthrough routinely surfaces UI laws the prose hid (e.g. Void `disabled={r.state !== "pending"}` while the API accepts completed voids) — write those discoveries into a closing law box, and check the prose section against them.