From 7c21f12cf9506a4dd88eb7ca239ce363ae50b532 Mon Sep 17 00:00:00 2001 From: deftio Date: Mon, 11 May 2026 20:59:17 -0700 Subject: [PATCH 1/3] Add Boilerroom field report: bwserve usage, discoverability gaps, API feedback Field report from building a ~5,500 LOC production app on bitwrench/bwserve. Covers what works well, the documentation/discoverability gap (the main issue), 4 genuine API gaps (sendAction naming, multi-field forms, modal primitive, register string bodies), JS-first styling insights, and LLM-driven development feedback. Co-Authored-By: Claude Opus 4.6 --- dev/boilerroom-field-report.md | 254 +++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 dev/boilerroom-field-report.md diff --git a/dev/boilerroom-field-report.md b/dev/boilerroom-field-report.md new file mode 100644 index 0000000..e735930 --- /dev/null +++ b/dev/boilerroom-field-report.md @@ -0,0 +1,254 @@ +# Boilerroom field report — bitwrench/bwserve in production + +Field report from building Boilerroom, a multi-perspective AI document review +app (~5,500 LOC) on bitwrench/bwserve. 5 tabs, 31 AI panelists, 3 AI +backends, 12 SQLite tables, SSE real-time streaming. Built over ~3 days. + +This is an honest assessment: what worked, what's genuinely missing, and — +critically — what appeared to be missing but was actually developer habit +colliding with undocumented capabilities. + +--- + +## Executive summary + +Bitwrench is a better framework than it appears to be. The capabilities are +ahead of the documentation. A developer using bitwrench today will underuse +it significantly — reaching for CSS classes instead of JS composition, +hand-coding things that are built in, missing APIs that exist — not because +the framework is lacking, but because nothing guides them toward the right +patterns. + +The single biggest issue is discoverability/documentation. The genuine API +gaps are minor (4 items). The documentation gap is the one that determines +whether bitwrench gets adopted or dismissed. + +--- + +## What works well (no changes needed) + +These are strong and correct: + +- **TACO model** — Composable, serializable, correct. Structure composition + works exactly as intended. +- **SSE transport** — Solid. Handles 5+ parallel AI streams pushing into the + feed simultaneously. No reconnection issues. +- **`data-bw-action` declarative binding** — Clean, scales to 20+ actions + without issues. No listener wiring, no event delegation boilerplate. +- **Component model (Level 0-2)** — Right levels of abstraction. Level 0 for + static pushes, Level 2 for stateful client widgets, clear upgrade path. +- **`client.render/patch/append/remove/mount/message/call`** — Good API + surface. Each verb does one thing well. +- **`o.state` + `o.render` + `bw.update(el)`** — Simple, correct reactivity. + No magic, no dependency tracking, no stale closures. +- **`o.handle`** — Clean imperative API for components. + `el.bw.setPanelists(list)` reads like a real API. +- **BCCL** — 50+ factories, behavioral composition works. +- **`bw.loadStyles()` theming** — Full design system from 2 seed colors. + +--- + +## The discoverability problem (THE issue) + +### What happened + +A competent developer built a full production app on bitwrench and: + +1. **Never found `client.mount()`** — Used `client.register()` with + string bodies to mount components. `client.mount()` exists + (client.js:254), does exactly what was needed, and returns a promise. + Discovered only by reading source code. + +2. **Wrote custom Enter key handlers** — Built `brInitChatInput` and + `brInitBoilerroomInput` as registered functions with keydown listeners. + bwclient.js already handles Enter on inputs by finding the nearest + `data-bw-action` button. The custom handlers were completely redundant. + +3. **Wrote 3,019 lines of CSS** — Created 13 separate button classes, 6 card + variants, 3 copies of markdown body styling. The TACO model already + supports JS-first styling via composable style strings in `a.style`, plus + function-valued attributes for runtime/hydration-time styling. None of + this was discovered during development. + +4. **Never used function-valued TACO attributes** — Functions in `a.style` + (plain function for hydration-time, IIFE for creation-time) enable + dynamic per-element styling composed from shared JS dictionaries. Never + reached for because it wasn't documented as a styling pattern. + +5. **Never found `bw.s()` style helpers** — Exist, solve style composition + on the fly. Not documented prominently. + +6. **Never used `bw.loadStyles()`** — Full theming engine, generates CSS + from seed colors. App hand-wrote 35 CSS variables instead. + +7. **Couldn't find `sendAction()`** — Tried `bw.action()` (doesn't exist), + eventually found `bw._bwClient.sendAction()` by reading bwclient.js + source. The underscore prefix actively discouraged using it. + +### Why this matters + +Every developer who picks up bitwrench will make these same mistakes. The +path of least resistance follows web-development habits (CSS classes, manual +event handlers, separate stylesheets), and nothing in the documentation +redirects toward bitwrench's actual idioms. + +This makes bitwrench look limited when it's actually capable. People will +evaluate it, hit friction, and conclude it can't do things it already does +well. + +### What would fix it + +**One document: "How to build a bwserve app"** — an opinionated guide that +leads with the right patterns from page one: + +1. **JS-first styling as the primary approach.** Show the style dictionary + pattern before mentioning CSS classes. Show function-valued attributes. + Show `bw.s()`. Show `bw.loadStyles()`. Explicitly call out the + anti-pattern of CSS-class-per-element. + + ```js + // The right way: composable JS style tokens + const S = { + btn: 'padding:6px 14px;border:1px solid #ccc;font-size:12px;cursor:pointer', + pill: 'border-radius:20px', + accent: 'background:#4361ee;color:#fff;border-color:#4361ee', + }; + { t: 'button', a: { style: `${S.btn};${S.pill};${S.accent}` }, c: 'Go' } + + // Function-valued for dynamic styling at hydration time + { t: 'div', a: { style: ()=> isActive ? `${S.card};${S.active}` : S.card }, c: '...' } + + // IIFE for dynamic styling at creation time + { t: 'div', a: { style: (()=> `${S.card};border-color:${color}`)() }, c: '...' } + ``` + +2. **`client.mount()` front and center.** The bwserve tutorial should show + `client.mount()` for interactive components before showing + `client.register()`. Most developers will encounter mount-a-component + before register-a-utility. + +3. **Complete `BwServeClient` API reference.** Document ALL methods: + `render`, `patch`, `append`, `remove`, `exec`, `call`, `register`, + `message`, `mount`, `inspect`, `screenshot`, `query`, `listen`. Currently + docs show 8 of ~13 methods. + +4. **Built-in behaviors page.** List everything bwclient.js already does: + - Enter key handling on inputs (algorithm documented) + - `inputValue` resolution (algorithm documented) + - Action delegation via `data-bw-action` + - What `data-bw-id` provides + +5. **Client-to-server communication.** Document `bw._bwClient.sendAction()` + prominently (or expose it as `bw.sendAction()`). This is the primary + programmatic client→server path and it's currently hidden behind an + underscore-prefixed internal object. + +--- + +## Genuine API gaps (4 items) + +These are real missing features, not documentation issues: + +### 1. `bw._bwClient.sendAction()` naming + +The primary client→server programmatic path looks like a private API. The +underscore prefix actively discourages its use. Should be promoted to +`bw.sendAction(name, data)` or `bw.action(name, data)` on the main `bw` +object. + +### 2. Multi-field form collection + +`data-bw-action` resolves one `inputValue` from the nearest sibling input. +Any form with 2+ fields requires a `client.exec()` workaround: + +```js +// Current workaround — ugly +client.exec(` + var name = document.getElementById("field-name").value; + var genre = document.getElementById("field-genre").value; + var persona = document.getElementById("field-persona").value; + bw._bwClient.sendAction("save-panelist", { name, genre, persona }); +`); +``` + +**Suggestion:** `data-bw-form="selector"` attribute on action buttons that +serializes all inputs/selects/textareas in the target container as a +key-value object (keyed by `name` attribute), sent alongside the action. + +### 3. No modal/dialog primitive + +Every app needs modals (confirmations, forms, alerts). Current pattern: + +```js +client.append('body', overlayTaco); +// ... later ... +client.remove('#modal-overlay-id'); +``` + +Works but is boilerplate every app will write. A `client.modal(taco, opts)` +or BCCL `makeModal({ title, body, actions })` would cover 90% of cases. + +### 4. `client.register()` string bodies + +`client.mount()` solves component mounting. But small utility functions +(disable/enable helpers, scroll-to-bottom, form collection) still need +`client.register()` with JS-as-a-string: + +```js +client.register('scrollToBottom', `function(id) { + var el = document.getElementById(id); + if (el) el.scrollTop = el.scrollHeight; +}`); +``` + +No syntax highlighting, no linting, errors only surface at runtime in the +browser console. The mitigation is putting logic in a client-side `app.js` +file instead, but this isn't obvious to new users. + +**Suggestion:** Document the `app.js` pattern as the recommended approach +for client-side utilities. Or: allow `client.register()` to accept a +function reference (serialized via `.toString()`) instead of requiring a +hand-written string. + +--- + +## LLM-driven development feedback + +Boilerroom was built with AI assistance (Claude) using bwserve's +`client.inspect()` and `client.screenshot()` for closed-loop development. + +### What worked + +- **`client.inspect(selector, { depth })`** — Useful for verifying structure + without opening a browser. Confirmed component mounting, element presence, + DOM structure. +- **Parameterized selectors** (`?selector=%23br-tab-body`) — Essential for + deep nesting. Body-level inspection cuts off too early. + +### What didn't work + +- **`client.screenshot()`** requires html2canvas served from + `/bw/lib/vendor/`. Not bundled in the npm package. Screenshots fail. +- **Inspect shows structure but not appearance.** Can verify `.br-header` + exists, but can't see if spacing/colors/layout are correct. CSS changes + are untestable without visual feedback. + +### What would help + +1. Screenshot without html2canvas dependency (native browser API or bundled) +2. Computed style queries — `client.inspect(selector, { computedStyles: ['display', 'background'] })` +3. Layout queries — bounding rect of elements for verifying flex layout + +--- + +## Conclusion + +Bitwrench has the right architecture. TACO is sound. The server-driven model +with SSE works. The component model is clean. JS-first styling with +function-valued attributes is the right approach. + +The gap is between what bitwrench can do and what developers discover it can +do. Close that gap — with an opinionated guide, complete API reference, and +prominent examples of the JS-first patterns — and bitwrench becomes a +serious contender in the front-end space. The framework is ready; the +on-ramp isn't. From d06bc8e7ffbe1dd4296e2dcf0c3b64fed00c1d00 Mon Sep 17 00:00:00 2001 From: deftio Date: Mon, 11 May 2026 21:55:18 -0700 Subject: [PATCH 2/3] Correct screenshot assessment: works with allowScreenshot flag, not broken html2canvas is vendored and served. The issue was the allowScreenshot: true server option defaulting to false. Another discoverability problem, not a missing feature. Updated LLM development loop section accordingly. Co-Authored-By: Claude Opus 4.6 --- dev/boilerroom-field-report.md | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/dev/boilerroom-field-report.md b/dev/boilerroom-field-report.md index e735930..78d346c 100644 --- a/dev/boilerroom-field-report.md +++ b/dev/boilerroom-field-report.md @@ -225,19 +225,29 @@ Boilerroom was built with AI assistance (Claude) using bwserve's - **Parameterized selectors** (`?selector=%23br-tab-body`) — Essential for deep nesting. Body-level inspection cuts off too early. -### What didn't work +### What appeared broken but wasn't (another discoverability issue) -- **`client.screenshot()`** requires html2canvas served from - `/bw/lib/vendor/`. Not bundled in the npm package. Screenshots fail. -- **Inspect shows structure but not appearance.** Can verify `.br-header` - exists, but can't see if spacing/colors/layout are correct. CSS changes - are untestable without visual feedback. +- **`client.screenshot()` works — but requires `allowScreenshot: true` in + server options.** html2canvas IS vendored in bitwrench + (`src/vendor/html2canvas.min.js`, 193KB) and IS served via an allowlisted + route. The flag defaults to `false` as a security gate. Without it, + screenshots silently fail. This was initially reported as "html2canvas not + bundled" — it was actually the missing server flag. -### What would help + This is another instance of the discoverability problem: a working feature + that appears broken because the required configuration isn't surfaced. -1. Screenshot without html2canvas dependency (native browser API or bundled) -2. Computed style queries — `client.inspect(selector, { computedStyles: ['display', 'background'] })` -3. Layout queries — bounding rect of elements for verifying flex layout + **Suggestion:** When `allowScreenshot` is false and a screenshot is + attempted, the rejection message should say: + `"Screenshot not enabled. Set allowScreenshot: true in bwserve.create() options."` + (It may already say this — if so, it wasn't visible enough in the error + chain to diagnose.) + +### What would still help + +1. Computed style queries — `client.inspect(selector, { computedStyles: ['display', 'background'] })` for programmatic CSS debugging without a full screenshot +2. Layout queries — bounding rect of elements for verifying flex layout +3. Document the `inspect()` + `screenshot()` combo as a first-class LLM development loop in the bwserve guide — this is a differentiating capability that no other framework offers as cleanly --- From d4ab780f1aaa26cd1b8ecb852c571c292009ab80 Mon Sep 17 00:00:00 2001 From: deftio Date: Mon, 11 May 2026 22:06:42 -0700 Subject: [PATCH 3/3] Revise assessment: core docs are strong, gap is bwserve-specific After reviewing "Thinking in Bitwrench" guide in detail: Sections 1-6, 8-10 cover mental model, JS-first styling, bw.s(), function-valued attrs, component levels, and composition patterns well. The gap is Section 7 (bwserve) which shows 8 of ~13 BwServeClient methods and misses mount, message, inspect, screenshot, sendAction. Revised executive summary and discoverability section to give credit where due and focus feedback on bwserve docs specifically. Also noted bitwrench runs in three modes (pure client, shim/loader, bwserve) and this report covers bwserve mode only. Co-Authored-By: Claude Opus 4.6 --- dev/boilerroom-field-report.md | 186 +++++++++++++++++---------------- 1 file changed, 97 insertions(+), 89 deletions(-) diff --git a/dev/boilerroom-field-report.md b/dev/boilerroom-field-report.md index 78d346c..d283f99 100644 --- a/dev/boilerroom-field-report.md +++ b/dev/boilerroom-field-report.md @@ -12,16 +12,26 @@ colliding with undocumented capabilities. ## Executive summary -Bitwrench is a better framework than it appears to be. The capabilities are -ahead of the documentation. A developer using bitwrench today will underuse -it significantly — reaching for CSS classes instead of JS composition, -hand-coding things that are built in, missing APIs that exist — not because -the framework is lacking, but because nothing guides them toward the right -patterns. - -The single biggest issue is discoverability/documentation. The genuine API -gaps are minor (4 items). The documentation gap is the one that determines -whether bitwrench gets adopted or dismissed. +Bitwrench is a capable framework with strong core documentation. The +"Thinking in Bitwrench" guide covers the mental model, JS-first styling +(`bw.s()`, `bw.css()`, function-valued attributes, `bw.loadStyles()`), +component levels, and composition patterns well. + +The gap is **bwserve-specific**. "Thinking in Bitwrench" is written for +client-side bitwrench (the primary mode). Section 7 (bwserve) covers 8 of +~13 `BwServeClient` methods and doesn't show the patterns needed for +server-driven apps — `client.mount()`, `client.message()`, +`inspect/screenshot`, `sendAction()`. A developer building a bwserve app +gets the conceptual foundation but hits a wall when they need the +server-side API. + +Important context: bitwrench runs in three modes — pure client-side (no +server needed), shim/loader (bare page that fetches TACOs statically or +dynamically), and bwserve (server pushes TACOs over SSE). This report +covers the bwserve mode. The client-side docs are not the problem. + +The genuine API gaps are minor (4 items). The bwserve documentation gap is +what caused most of the friction in this project. --- @@ -48,101 +58,90 @@ These are strong and correct: --- -## The discoverability problem (THE issue) - -### What happened - -A competent developer built a full production app on bitwrench and: - -1. **Never found `client.mount()`** — Used `client.register()` with - string bodies to mount components. `client.mount()` exists - (client.js:254), does exactly what was needed, and returns a promise. - Discovered only by reading source code. - -2. **Wrote custom Enter key handlers** — Built `brInitChatInput` and - `brInitBoilerroomInput` as registered functions with keydown listeners. - bwclient.js already handles Enter on inputs by finding the nearest - `data-bw-action` button. The custom handlers were completely redundant. +## The bwserve documentation gap -3. **Wrote 3,019 lines of CSS** — Created 13 separate button classes, 6 card - variants, 3 copies of markdown body styling. The TACO model already - supports JS-first styling via composable style strings in `a.style`, plus - function-valued attributes for runtime/hydration-time styling. None of - this was discovered during development. +### What's already well-documented (credit where due) -4. **Never used function-valued TACO attributes** — Functions in `a.style` - (plain function for hydration-time, IIFE for creation-time) enable - dynamic per-element styling composed from shared JS dictionaries. Never - reached for because it wasn't documented as a styling pattern. +The "Thinking in Bitwrench" guide covers the core mental model effectively: -5. **Never found `bw.s()` style helpers** — Exist, solve style composition - on the fly. Not documented prominently. +- **Section 2 (Styling)** — JS-first styling, `bw.s()`, `bw.css()`, + `bw.responsive()`, `bw.loadStyles()`, function-as-style-value, `bw.u()` + utility shorthand. All the patterns needed. +- **Section 3** — Function-valued attributes with both timing modes (IIFE + vs plain function), clearly explained with examples. +- **Section 5** — Level 0/1/2 component model, when to use which. +- **Section 6** — Handles, slots, pub/sub. +- **Framework translation table** — Strong teaching tool for developers + coming from React/Vue/Svelte. -6. **Never used `bw.loadStyles()`** — Full theming engine, generates CSS - from seed colors. App hand-wrote 35 CSS variables instead. +A developer who reads the full guide before starting would have the right +mental model. The styling patterns, composition approaches, and component +levels are all there. -7. **Couldn't find `sendAction()`** — Tried `bw.action()` (doesn't exist), - eventually found `bw._bwClient.sendAction()` by reading bwclient.js - source. The underscore prefix actively discouraged using it. +### What happened anyway -### Why this matters +Despite the docs existing, a developer building a bwserve app: -Every developer who picks up bitwrench will make these same mistakes. The -path of least resistance follows web-development habits (CSS classes, manual -event handlers, separate stylesheets), and nothing in the documentation -redirects toward bitwrench's actual idioms. +1. **Wrote 3,019 lines of CSS** instead of using the JS-first styling + patterns documented in Section 2. The styling section is thorough but + written for client-side bitwrench. A bwserve developer building TACO on + the server side might skip to Section 7 and never read Section 2, + assuming styling is a separate concern. -This makes bitwrench look limited when it's actually capable. People will -evaluate it, hit friction, and conclude it can't do things it already does -well. +2. **Never found `client.mount()`** — Section 7 shows `render`, `patch`, + `append`, `remove`, `on`, `register`, `call`, `batch` — 8 methods. It + does NOT show `mount`, `message`, `inspect`, or `screenshot`. These 5 + missing methods are arguably the most important for real bwserve apps. -### What would fix it +3. **Wrote custom Enter key handlers** — bwclient.js built-in behavior. + Not documented in "Thinking in Bitwrench" or (apparently) in the bwserve + tutorial. Discovered by reading source. -**One document: "How to build a bwserve app"** — an opinionated guide that -leads with the right patterns from page one: +4. **Couldn't find `sendAction()`** — The programmatic client→server path. + Not in Section 7 or the bwserve tutorial. -1. **JS-first styling as the primary approach.** Show the style dictionary - pattern before mentioning CSS classes. Show function-valued attributes. - Show `bw.s()`. Show `bw.loadStyles()`. Explicitly call out the - anti-pattern of CSS-class-per-element. +5. **Didn't know `allowScreenshot: true` was needed** — Assumed screenshots + were broken. The flag and its requirement aren't surfaced in the guide. - ```js - // The right way: composable JS style tokens - const S = { - btn: 'padding:6px 14px;border:1px solid #ccc;font-size:12px;cursor:pointer', - pill: 'border-radius:20px', - accent: 'background:#4361ee;color:#fff;border-color:#4361ee', - }; - { t: 'button', a: { style: `${S.btn};${S.pill};${S.accent}` }, c: 'Go' } +### The pattern - // Function-valued for dynamic styling at hydration time - { t: 'div', a: { style: ()=> isActive ? `${S.card};${S.active}` : S.card }, c: '...' } +Items 1 is a developer-habit problem — the docs exist, the developer didn't +read them (or read the wrong section). Items 2-5 are genuine bwserve doc +gaps — the information isn't in the guide at all. - // IIFE for dynamic styling at creation time - { t: 'div', a: { style: (()=> `${S.card};border-color:${color}`)() }, c: '...' } - ``` +### What would fix it -2. **`client.mount()` front and center.** The bwserve tutorial should show - `client.mount()` for interactive components before showing - `client.register()`. Most developers will encounter mount-a-component - before register-a-utility. +**Expand Section 7 of "Thinking in Bitwrench"** or create a companion +**"Thinking in bwserve"** that covers the full server-driven API: -3. **Complete `BwServeClient` API reference.** Document ALL methods: +1. **Complete `BwServeClient` method reference.** All ~13 methods: `render`, `patch`, `append`, `remove`, `exec`, `call`, `register`, - `message`, `mount`, `inspect`, `screenshot`, `query`, `listen`. Currently - docs show 8 of ~13 methods. + `message`, `mount`, `inspect`, `screenshot`, `query`, `listen`. + Currently 8 of 13 are documented. + +2. **`client.mount()` front and center.** Show it for interactive components + before showing `client.register()`. Most bwserve developers will need + mount-a-component before register-a-utility. -4. **Built-in behaviors page.** List everything bwclient.js already does: - - Enter key handling on inputs (algorithm documented) - - `inputValue` resolution (algorithm documented) +3. **Built-in bwclient.js behaviors.** List everything the thin client + already does automatically: + - Enter key handling on inputs (algorithm: find nearest `data-bw-action`) + - `inputValue` resolution (algorithm: `el.closest("div").querySelector("input")`) - Action delegation via `data-bw-action` - What `data-bw-id` provides + - `allowScreenshot` flag requirement -5. **Client-to-server communication.** Document `bw._bwClient.sendAction()` +4. **Client-to-server communication.** Document `bw._bwClient.sendAction()` prominently (or expose it as `bw.sendAction()`). This is the primary programmatic client→server path and it's currently hidden behind an underscore-prefixed internal object. +5. **Cross-reference to styling.** A bwserve developer building TACO on the + server will naturally construct `a: { class: '...' }` and write a CSS + file. A note in Section 7 pointing back to Section 2 ("your TACO styles + are JS strings — compose them from dictionaries, not CSS classes") would + intercept this habit at the right moment. + --- ## Genuine API gaps (4 items) @@ -253,12 +252,21 @@ Boilerroom was built with AI assistance (Claude) using bwserve's ## Conclusion -Bitwrench has the right architecture. TACO is sound. The server-driven model -with SSE works. The component model is clean. JS-first styling with -function-valued attributes is the right approach. - -The gap is between what bitwrench can do and what developers discover it can -do. Close that gap — with an opinionated guide, complete API reference, and -prominent examples of the JS-first patterns — and bitwrench becomes a -serious contender in the front-end space. The framework is ready; the -on-ramp isn't. +Bitwrench has the right architecture and better core documentation than +initially credited. The "Thinking in Bitwrench" guide effectively teaches +the mental model, JS-first styling, component composition, and client-side +patterns. The framework runs in multiple modes (pure client, shim/loader, +bwserve) and the client-side docs are solid. + +The gap is specifically in **bwserve documentation**. Section 7 of "Thinking +in Bitwrench" covers the concept but not the full API. A developer building +a server-driven app needs `client.mount()`, `client.message()`, +`inspect/screenshot`, `sendAction()`, and bwclient.js built-in behaviors — +none of which are in the current guide. Expanding Section 7 (or creating a +companion "Thinking in bwserve" guide) with the complete API and +cross-references to the styling section would close the gap. + +The genuine API issues (sendAction naming, multi-field forms, modal +primitive, register string bodies) are minor and well-defined. The framework +itself is sound and — given proper bwserve documentation — ready to be a +serious contender.