docs
This commit is contained in:
parent
dc947d16b9
commit
465cc74796
1 changed files with 136 additions and 0 deletions
|
|
@ -402,6 +402,142 @@ then log results in Section 10 before moving on.
|
|||
- _Next:_ `styles` + `message` template + `GET /message/:id` (single-message
|
||||
primitive).
|
||||
|
||||
- **2026-08-06 — Phases 1–7 built & backend verified on brb.city.**
|
||||
- **All 16 templates + 10 routes written** (ids in the maps above). Structure
|
||||
`aim` #44 is live at `https://brb.city/aim/`.
|
||||
- **Design pivot (recorded so §4–6 match reality): identity is fully
|
||||
client-side.** localStorage holds `aim:handle` + `aim:client_id` (a stable
|
||||
per-browser UUID). The socket carries them on an `identify` event (presence)
|
||||
and each `send` (authorship + push exclusion). The server *trusts* the
|
||||
client's declared identity — correct for a fun playground, and it kills the
|
||||
"forgets who you are" + session-churn class of bugs outright. No server-side
|
||||
alias/session juggling remains.
|
||||
- **The four reported bugs, resolved:**
|
||||
- *Forgets you* → localStorage handle + one stable alias per handle
|
||||
(`getOrCreateAlias`), auto-seeded from the logged-in Bliss user.
|
||||
- *Self-notify push* → subscriptions keyed by `endpoint`, owned by stable
|
||||
`client_id`; fan-out is `subsExcludingClient(senderClientId)`. Your own
|
||||
device is structurally excluded regardless of name/session changes.
|
||||
- *Noisy presence* → counts kept **per person, not per socket**, with a 4s
|
||||
debounce on sign-off, so tabs/reconnects don't spam. (`arrive`/`depart` in
|
||||
the WS handler.)
|
||||
- *Broken single-message* → `getMessageById` rewritten with the correct join;
|
||||
it's now the backbone of the socket-as-pointer-bus design.
|
||||
- **Socket-as-bus confirmed live** via a Node `ws` client: `identify` →
|
||||
presence-line broadcast; `send` → persisted (`message #4`) + a `msg-pointer`
|
||||
broadcast of exactly
|
||||
`<div hx-get="/aim/message/4?zone=z9" hx-trigger="load" hx-swap="outerHTML">`
|
||||
— no message markup crosses the socket. `GET /aim/message/1` renders the AIM
|
||||
line (red bold name, gray timestamp) with **unescaped** `<b>`/`<marquee>`
|
||||
intact. First-render null-slice bug (Eta ASI: an eval block must not start
|
||||
with `(`) found & fixed in `transcript`.
|
||||
- **`req.currentUser` added** (minimal `{id, username}`) in **local**
|
||||
`index.js` + `getUserById` in `db.js` (syntax-checked). ⚠️ This repo is the
|
||||
*local* copy; brb.city runs from `/home/nodejs/bliss2` on another host — **the
|
||||
index.js/db.js change needs deploy + restart there to take effect.** Until
|
||||
then templates fall back to `"Guest"` (graceful; nothing breaks).
|
||||
- Seeded one welcome message; cleared all test rows.
|
||||
|
||||
### Verified ✅ vs. remaining ⏳
|
||||
- ✅ Fresh schema + library (alias stability, verbatim HTML, range/catchup/push helpers)
|
||||
- ✅ `GET /message/:id` single-message primitive (unescaped content)
|
||||
- ✅ `WS /room`: identify→presence, send→persist→pointer broadcast, catchup
|
||||
- ✅ Full page, `/live`, `/compose`, `/frozen` render without error
|
||||
- ✅ Socket ships pointers only; message route is the single render source
|
||||
- ⏳ **Browser check** (Playwright MCP wasn't available this session): the
|
||||
client paths — compose→`chat:send`→ws-bridge ship, `chat:message` emit on
|
||||
arrival, localStorage default handle, rename, autoscroll, push subscribe —
|
||||
are written but not yet driven in a real browser. Do this next session.
|
||||
- ⏳ **Deploy** local `index.js`/`db.js` to brb.city + restart (pm2 `foo`) to
|
||||
enable the logged-in-user default.
|
||||
- ⏳ **Phase 8**: an `aimgpt`-style demo page nesting `/live` + `/compose` (+ the
|
||||
sheep) to show the parts compose.
|
||||
|
||||
- **2026-08-06 — Browser verification + the send-path bug (found via Playwright).**
|
||||
- Got Playwright MCP working (it wanted chromium build 1237; symlinked the
|
||||
installed `chromium-1234` → `chromium-1237` in `~/.cache/ms-playwright`).
|
||||
- **Sending was broken — real bug, now fixed.** Eta's `<%= %>` HTML-escapes, so
|
||||
`var dflt = <%= JSON.stringify('Guest') %>;` rendered as
|
||||
`var dflt = "Guest";` **inside the `<script>`** → "Unexpected token
|
||||
'&'" → the entire `ws-bridge` script threw → `window.aimId` undefined → no
|
||||
`chat:send` listener → messages dispatched into the void (textarea cleared,
|
||||
nothing shipped). Fix: use `<%~ %>` (raw) for JSON in every script context
|
||||
(`ws-bridge`, `identity-boot`, `push-setup`).
|
||||
- Also fixed: `_hyperscript` has **no ternary** (`?:`) — the screen-name span
|
||||
`set my innerHTML to (window.aimId ? … : …)` threw. Replaced with a plain-JS
|
||||
`.aim-screenname` painter in `identity-boot`.
|
||||
- **Verified in a real browser (0 console errors):** typed a message, pressed
|
||||
Enter → full round trip (compose → `chat:send` → ws-bridge ship → persist →
|
||||
`msg-pointer` broadcast → `hx-get /message/2` → rendered). Presence line
|
||||
"Guest signed on." shows. AIM aesthetic confirmed via screenshot
|
||||
(`aim-working.png`): blue title bar, silver bevel, small serif transcript,
|
||||
color-coded bold names, gray timestamps, toolbar, compose. `<marquee>` runs.
|
||||
- Note: the Bliss inspector 🔍 button floats over the Send button (Enter still
|
||||
sends). Handle still defaults to "Guest" until the `req.currentUser` change
|
||||
is deployed to brb.city.
|
||||
|
||||
- **2026-08-06 — Mobile pass.**
|
||||
- Root cause of "text too small on mobile": **no `<meta viewport>`** — page
|
||||
rendered at desktop width and scaled down. Added a mobile head-injection on
|
||||
structure 44 (viewport with `user-scalable=no` + `interactive-widget=resizes-content`,
|
||||
theme-color, apple PWA metas, `touch-action:manipulation` to kill double-tap
|
||||
zoom, favicon + apple-touch-icon links).
|
||||
- Bumped fonts (16px base / 13px timestamps / 13px titlebar), enlarged compose
|
||||
(3 rows, min-height 84px, 16px to avoid iOS focus-zoom), safe-area insets on
|
||||
titlebar/compose.
|
||||
- **AIM favicon:** wget'd the real AIM running-man logo (user OK'd for the test
|
||||
instance), generated 32/180/192/512 + `.ico` via ImageMagick, uploaded to
|
||||
structure 44 (served `brb.city/44/*`), wired manifest icons + head links.
|
||||
- **Keyboard resize (user chose PURE CSS, zero JS):** layout already shrinks
|
||||
via the flex column (`.aim-transcript { flex:1; min-height:0; overflow }`) +
|
||||
`height:100dvh`; `interactive-widget=resizes-content` makes Android shrink
|
||||
the viewport with no JS. iOS Safari has no CSS-only fix, so it falls back to
|
||||
the browser's shift-up. (Briefly tried a `visualViewport` script — verified
|
||||
it shrank 844→544px — then removed it per the clean-CSS decision.)
|
||||
|
||||
- **2026-08-06 — File upload (frontend compression).**
|
||||
- **Architecture:** compression is 100% frontend (the handler sandbox exposes
|
||||
no fs/sharp/ffmpeg). Images: canvas downscale + JPEG quality loop to <1MB
|
||||
(verified: crushed a 21MB PNG). Videos: **ffmpeg.wasm** transcode to H.264/AAC
|
||||
mp4 targeting a bitrate from clip duration (verified: **4.6MB → 986KB**,
|
||||
playable 640×360). Other types: uploaded as-is → inline `<a>` link.
|
||||
Images/videos embed as `<img>`/`<video>`. Toolbar `attach` control.
|
||||
- **Upload path = disk.** `POST /upload` → `require('files').saveFile` →
|
||||
`public/<sid>/<name>`, served at `/<sid>/<name>`; returns same-origin path.
|
||||
Found + fixed a framework bug: `saveFile` did `path.join(__dirname,"public",
|
||||
structureId)` with a **numeric** id (only worked from the workshop route
|
||||
which passes a string) → `String()` coercion in `index.js` (reproduced
|
||||
before/after). ⚠️ **Needs the index.js deploy to brb.city** for uploads to
|
||||
persist live (same deploy as `req.currentUser`).
|
||||
- **ffmpeg.wasm hosting:** the 5 assets (ffmpeg.js, 814.ffmpeg.js worker,
|
||||
util, core.js, 32MB core.wasm) are uploaded to the structure's files
|
||||
(`/44/*`, same-origin) and lazy-loaded on first video; the service worker
|
||||
caches them so they load once. Key gotcha (cost several iterations): in
|
||||
ffmpeg.js 0.12, passing `classWorkerURL` forces a **module** worker, but the
|
||||
UMD worker chunk is **classic** (`importScripts`) → "failed to import
|
||||
ffmpeg-core.js". Fix: load `ffmpeg.js` same-origin and **do NOT pass
|
||||
classWorkerURL** — webpack auto publicPath resolves its default (classic,
|
||||
same-origin) worker to `/44/814.ffmpeg.js`. core/wasm handed in as
|
||||
`toBlobURL` blobs.
|
||||
- iOS caveat: ffmpeg.wasm is memory-bound in WKWebView; short clips fine, very
|
||||
large/long ones may fail. Documented, acceptable for the playground.
|
||||
|
||||
### How to embed the pieces (the payoff)
|
||||
```html
|
||||
<!-- live transcript, no compose -->
|
||||
<div hx-get="/aim/live?zone=abc" hx-trigger="load"></div>
|
||||
<!-- compose only, no transcript -->
|
||||
<div hx-get="/aim/compose?zone=abc" hx-trigger="load"></div>
|
||||
<!-- a frozen slice of history -->
|
||||
<div hx-get="/aim/frozen?after=0&before=50" hx-trigger="load"></div>
|
||||
<!-- one message -->
|
||||
<div hx-get="/aim/message/1?zone=abc" hx-trigger="load"></div>
|
||||
```
|
||||
Rule: **one zone == one ws-bridge (socket).** Compose raw pieces together only
|
||||
with distinct zones, or just use `GET /aim/` (which includes exactly one).
|
||||
Cross-structure port preserved: dispatch `chat:say`/`chat:send` on `body` and a
|
||||
bridge ships it (sheepfriend/sheepgpt keep working).
|
||||
|
||||
---
|
||||
|
||||
## 11. Decisions (resolved 2026-08-06)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue