# Static JS prototype routing and verification

Use this when updating a static HTML/JS prototype served by `python -m http.server` behind nginx (common Paperclip/prototype pattern).

## Pitfalls observed

- `curl` of the route only proves the static shell loads; it will not show client-rendered content injected by JS. Use browser automation or run the module renderer directly in Node for content assertions.
- Browser module scripts can remain cached after edits. Cache-bust both the page URL and the module URL, e.g. `src="./src/app.mjs?v=YYYYMMDDx"`, not just `https://site/path?v=...`.
- If you change shared CSS (hover/focus/toast styles), cache-bust stylesheet links too, e.g. `styles.css?v=YYYYMMDDx`; otherwise behavior tests can pass while the public visual state still uses old styling.
- Direct subpaths like `/onboarding/` commonly serve `onboarding/index.html`; if that file loads a shared JS router, normalize trailing slashes before route lookup:

```js
const normalizedPath = pathname !== '/' && pathname.endsWith('/')
  ? pathname.slice(0, -1)
  : pathname;
```

- For nested static pages, keep asset paths relative to depth:
  - `/index.html`: `./src/app.mjs`
  - `/onboarding/index.html`: `../src/app.mjs`
  - `/admin/reviews/index.html`: `../../src/app.mjs`

## Verification pattern

1. Run syntax/tests first:

```bash
npm run check && npm run smoke
```

2. Verify all public routes with a real browser, not only curl:

- `/` contains the requested dashboard cards and excludes moved/removed sections.
- New route pages contain the moved sections.
- Navigation tabs exist and deep links load directly.
- Browser console has no module load/path errors.
- For click feedback/toasts, verify immediately after the click (or trigger via `document.querySelector(...).click()` in console) because short-lived toasts may auto-hide before a normal click+inspection round-trip completes. Check both text content and `hidden`/visibility class state.

3. If browser still shows stale UI after passing tests, update module query strings in all route `index.html` files and reload with a fresh page query.
