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
|
- _Next:_ `styles` + `message` template + `GET /message/:id` (single-message
|
||||||
primitive).
|
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)
|
## 11. Decisions (resolved 2026-08-06)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue