bitwrench 2.0.32 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -125
- package/dist/bitwrench-bccl.cjs.js +349 -188
- package/dist/bitwrench-bccl.cjs.min.js +2 -39
- package/dist/bitwrench-bccl.cjs.min.js.gz +0 -0
- package/dist/bitwrench-bccl.esm.js +349 -188
- package/dist/bitwrench-bccl.esm.min.js +2 -39
- package/dist/bitwrench-bccl.esm.min.js.gz +0 -0
- package/dist/bitwrench-bccl.umd.js +349 -188
- package/dist/bitwrench-bccl.umd.min.js +2 -39
- package/dist/bitwrench-bccl.umd.min.js.gz +0 -0
- package/dist/bitwrench-code-edit.cjs.js +17 -6
- package/dist/bitwrench-code-edit.cjs.min.js +2 -20
- package/dist/bitwrench-code-edit.es5.js +8 -3
- package/dist/bitwrench-code-edit.es5.min.js +2 -19
- package/dist/bitwrench-code-edit.esm.js +17 -6
- package/dist/bitwrench-code-edit.esm.min.js +2 -19
- package/dist/bitwrench-code-edit.umd.js +17 -6
- package/dist/bitwrench-code-edit.umd.min.js +2 -19
- package/dist/bitwrench-code-edit.umd.min.js.gz +0 -0
- package/dist/bitwrench-debug.js +1 -1
- package/dist/bitwrench-debug.min.js +1 -1
- package/dist/bitwrench-lean.cjs.js +2492 -1628
- package/dist/bitwrench-lean.cjs.min.js +2 -80
- package/dist/bitwrench-lean.cjs.min.js.gz +0 -0
- package/dist/bitwrench-lean.es5.js +2740 -1838
- package/dist/bitwrench-lean.es5.min.js +2 -49
- package/dist/bitwrench-lean.es5.min.js.gz +0 -0
- package/dist/bitwrench-lean.esm.js +2492 -1628
- package/dist/bitwrench-lean.esm.min.js +2 -80
- package/dist/bitwrench-lean.esm.min.js.gz +0 -0
- package/dist/bitwrench-lean.umd.js +2492 -1628
- package/dist/bitwrench-lean.umd.min.js +2 -80
- package/dist/bitwrench-lean.umd.min.js.gz +0 -0
- package/dist/bitwrench-util-color.cjs.js +251 -0
- package/dist/bitwrench-util-color.cjs.min.js +3 -0
- package/dist/bitwrench-util-color.es5.js +256 -0
- package/dist/bitwrench-util-color.es5.min.js +3 -0
- package/dist/bitwrench-util-color.esm.js +241 -0
- package/dist/bitwrench-util-color.esm.min.js +3 -0
- package/dist/bitwrench-util-color.umd.js +257 -0
- package/dist/bitwrench-util-color.umd.min.js +3 -0
- package/dist/bitwrench-util-css.cjs.js +2 -1
- package/dist/bitwrench-util-css.cjs.min.js +2 -21
- package/dist/bitwrench-util-css.es5.js +2 -1
- package/dist/bitwrench-util-css.es5.min.js +2 -20
- package/dist/bitwrench-util-css.esm.js +2 -1
- package/dist/bitwrench-util-css.esm.min.js +1 -19
- package/dist/bitwrench-util-css.umd.js +2 -1
- package/dist/bitwrench-util-css.umd.min.js +2 -20
- package/dist/bitwrench-util-css.umd.min.js.gz +0 -0
- package/dist/bitwrench.cjs.js +2826 -1801
- package/dist/bitwrench.cjs.min.js +2 -99
- package/dist/bitwrench.cjs.min.js.gz +0 -0
- package/dist/bitwrench.css +403 -479
- package/dist/bitwrench.d.ts +70 -73
- package/dist/bitwrench.es5.js +3106 -2020
- package/dist/bitwrench.es5.min.js +2 -67
- package/dist/bitwrench.es5.min.js.gz +0 -0
- package/dist/bitwrench.esm.js +2826 -1801
- package/dist/bitwrench.esm.min.js +2 -99
- package/dist/bitwrench.esm.min.js.gz +0 -0
- package/dist/bitwrench.min.css +1 -1
- package/dist/bitwrench.umd.js +2826 -1801
- package/dist/bitwrench.umd.min.js +2 -99
- package/dist/bitwrench.umd.min.js.gz +0 -0
- package/dist/builds.json +222 -134
- package/dist/bwserve.cjs.js +289 -282
- package/dist/bwserve.d.ts +157 -0
- package/dist/bwserve.esm.js +290 -283
- package/dist/sri.json +54 -46
- package/docs/README.md +6 -3
- package/docs/app-patterns.md +7 -6
- package/docs/bitwrench-for-wasm.md +53 -54
- package/docs/bitwrench-mcp.md +2 -2
- package/docs/bitwrench-northstar-principles.md +406 -0
- package/docs/bitwrench-taco-schema-discussion.md +2 -2
- package/docs/bitwrench_api.md +191 -106
- package/docs/bitwrench_typescript_usage.md +5 -5
- package/docs/bw-attach.md +29 -75
- package/docs/bwserve.md +200 -168
- package/docs/cli.md +36 -12
- package/docs/component-cheatsheet.md +2 -2
- package/docs/component-library.md +4 -4
- package/docs/component-lifecycle.md +234 -0
- package/docs/drift-lint.md +268 -0
- package/docs/framework-translation-table.md +4 -4
- package/docs/llm-bitwrench-guide.md +60 -50
- package/docs/routing.md +11 -13
- package/docs/state-management.md +110 -109
- package/docs/taco-format.md +13 -14
- package/docs/theming.md +13 -3
- package/docs/thinking-in-bitwrench.md +858 -983
- package/docs/tutorial-bwserve.md +37 -36
- package/docs/tutorial-embedded.md +10 -21
- package/docs/tutorial-website.md +2 -2
- package/package.json +38 -7
- package/readme.html +262 -161
- package/src/bitwrench-bccl-entry.js +2 -2
- package/src/bitwrench-bccl.js +346 -185
- package/src/bitwrench-code-edit.js +16 -5
- package/src/bitwrench-color-utils.js +117 -181
- package/src/bitwrench-file-ops.js +2 -2
- package/src/bitwrench-lean.js +4 -3
- package/src/bitwrench-router.js +5 -2
- package/src/bitwrench-styles.js +420 -504
- package/src/bitwrench-util-color.js +240 -0
- package/src/bitwrench-util-css.js +1 -0
- package/src/bitwrench-utils.js +4 -0
- package/src/bitwrench.d.ts +70 -73
- package/src/bitwrench.h +5 -0
- package/src/bitwrench.js +1939 -933
- package/src/bwserve/attach.js +0 -1
- package/src/bwserve/bwclient.js +172 -32
- package/src/bwserve/bwshell.js +0 -4
- package/src/bwserve/client.js +59 -220
- package/src/bwserve/index.js +59 -26
- package/src/bwserve.d.ts +157 -0
- package/src/bwserve.h +5 -0
- package/src/cli/attach.js +12 -75
- package/src/cli/convert.js +2 -2
- package/src/cli/serve.js +37 -35
- package/src/generate-css.js +1 -1
- package/src/mcp/knowledge.js +4 -4
- package/src/mcp/live.js +21 -13
- package/src/mcp/tools.js +0 -1
- package/src/version.js +3 -7
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
# Bitwrench North Star
|
|
2
|
+
|
|
3
|
+
Read this before every implementation task. If your code violates these
|
|
4
|
+
principles, stop and rethink.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## The core idea
|
|
9
|
+
|
|
10
|
+
A JS object can describe a UI component: its tag, attributes, content,
|
|
11
|
+
state, behavior, and lifecycle. That object is called a TACO:
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
{
|
|
15
|
+
t: 'div', // HTML tag
|
|
16
|
+
a: { class: 'card', onclick: fn }, // attributes (including event handlers)
|
|
17
|
+
c: [ /* child TACOs or strings */ ], // content
|
|
18
|
+
o: { // options: state, lifecycle, methods
|
|
19
|
+
state: { count: 0 },
|
|
20
|
+
handle: { increment: function(el) { /* ... */ } }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This is the entire premise. Everything else follows from it.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## The chain of consequences
|
|
30
|
+
|
|
31
|
+
Each decision below follows from the one above it. If a reviewer
|
|
32
|
+
disagrees with a consequence, trace back to the root -- the argument
|
|
33
|
+
is only as strong as the chain.
|
|
34
|
+
|
|
35
|
+
### 1. TACO is a JS object, not a template
|
|
36
|
+
|
|
37
|
+
A TACO is a plain JavaScript object literal. No special syntax (JSX),
|
|
38
|
+
no string interpolation (template literals), no domain-specific language
|
|
39
|
+
(.vue, .svelte). Just `{t, a, c, o}`.
|
|
40
|
+
|
|
41
|
+
**Why this matters:** JS objects are built into the language. Every JS
|
|
42
|
+
runtime, every browser, every server, every LLM can produce them without
|
|
43
|
+
any tooling. TypeScript can type-check them (bitwrench ships .d.ts).
|
|
44
|
+
JSON Schema can validate them structurally. They serialize to JSON
|
|
45
|
+
(minus functions in `o`). They can be generated, inspected, validated,
|
|
46
|
+
and transmitted by any tool that understands JavaScript or JSON.
|
|
47
|
+
|
|
48
|
+
We don't use TypeScript or JSX as a prerequisite because they require
|
|
49
|
+
external compilers. TypeScript is supported and valuable (bitwrench
|
|
50
|
+
ships .d.ts files for full type checking), but it is never required.
|
|
51
|
+
The architecture works without a build step. Period.
|
|
52
|
+
|
|
53
|
+
### 2. UI can be created at compile time or runtime
|
|
54
|
+
|
|
55
|
+
Because TACO is a JS object, it can be constructed at any point:
|
|
56
|
+
- At write time: a developer hand-writes `{t: 'div', ...}`
|
|
57
|
+
- At build time: a tool generates optimized TACO factories
|
|
58
|
+
- At runtime: a function constructs TACOs from data, user input, or API responses
|
|
59
|
+
- At serve time: a server in any language (Python, Go, Rust) generates
|
|
60
|
+
TACO-shaped JSON and pushes it to the client
|
|
61
|
+
|
|
62
|
+
No compilation step sits between "component defined" and "component
|
|
63
|
+
rendered." A TACO written in a `<script>` tag works identically to one
|
|
64
|
+
produced by a bundler.
|
|
65
|
+
|
|
66
|
+
### 3. CSS can be generated at compile time or runtime
|
|
67
|
+
|
|
68
|
+
The same logic applies to CSS. Because bitwrench generates CSS from JS
|
|
69
|
+
objects (palette values, spacing tokens, component configuration), CSS
|
|
70
|
+
is just another output of JS functions. This means:
|
|
71
|
+
|
|
72
|
+
- No CSS preprocessors (Less, Sass) -- JS functions are the preprocessor
|
|
73
|
+
- CSS custom properties are a web platform feature and can coexist in
|
|
74
|
+
user CSS (see github.com/deftio/quikchat for that style of thinking),
|
|
75
|
+
but bitwrench's design system does not depend on them -- values come
|
|
76
|
+
from palette objects in JS
|
|
77
|
+
- No utility-class framework (Tailwind) -- bitwrench generates equivalent
|
|
78
|
+
CSS from design tokens at runtime. You get Tailwind's result without
|
|
79
|
+
Tailwind's build step or class proliferation
|
|
80
|
+
- Inline styles compose via `bw.s()` (merge style objects to a string),
|
|
81
|
+
graduating to `bw.css()` (generate class-based CSS from JS objects)
|
|
82
|
+
when you need pseudo-classes, media queries, or keyframes
|
|
83
|
+
- Dark mode is palette inversion, not a parallel set of CSS overrides
|
|
84
|
+
- Theme switching = swap the palette object, regenerate. One function call.
|
|
85
|
+
|
|
86
|
+
### 4. TACO definitions carry everything a component needs
|
|
87
|
+
|
|
88
|
+
A TACO is not just layout. It includes:
|
|
89
|
+
- **Structure**: tag, attributes, children (`t`, `a`, `c`)
|
|
90
|
+
- **Styling**: class names, inline styles, or references to design tokens
|
|
91
|
+
- **Behavior**: event handlers directly in attributes (`onclick`, `onchange`, etc.)
|
|
92
|
+
- **State**: initial state object (`o.state`)
|
|
93
|
+
- **Lifecycle**: mount/unmount hooks (`o.mounted`, `o.unmount`)
|
|
94
|
+
- **Public API**: handle methods and slots (`o.handle`, `o.slots`)
|
|
95
|
+
- **Identity**: component type tag for discovery (`o.type`)
|
|
96
|
+
|
|
97
|
+
This is the MFC/Swing/Delphi model: the component is a self-contained
|
|
98
|
+
object with an API. The rendering substrate (DOM, GDI, AWT) is an
|
|
99
|
+
implementation detail. You call the component's methods; it manages its
|
|
100
|
+
own display.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
WRONG: el.querySelector('.title').textContent = 'New'; // reach into the DOM
|
|
104
|
+
RIGHT: el.bw.setTitle('New'); // call the component
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 5. TACO is consumed, not retained
|
|
108
|
+
|
|
109
|
+
After bitwrench creates a DOM element from a TACO, the TACO is gone.
|
|
110
|
+
All information from `o` is decomposed onto the DOM element (state,
|
|
111
|
+
methods, hooks, slots). bitwrench does not keep a shadow tree, a virtual
|
|
112
|
+
DOM, or a reference to the original specification.
|
|
113
|
+
|
|
114
|
+
This is fundamentally different from React (which retains element
|
|
115
|
+
descriptors for diffing) and Vue (which wraps state in reactive proxies).
|
|
116
|
+
There is no virtual intermediary. The DOM IS the component. querySelector
|
|
117
|
+
IS the component registry. Browser DevTools IS the inspector.
|
|
118
|
+
|
|
119
|
+
If you need another instance of the same component, call the factory
|
|
120
|
+
function again. Clone TACOs (data), not DOM nodes (live objects).
|
|
121
|
+
|
|
122
|
+
### 6. The pure path from TACO to mounted component has distinct phases
|
|
123
|
+
|
|
124
|
+
define -> create -> hydrate -> mount -> update -> unmount
|
|
125
|
+
|
|
126
|
+
In practice, create+hydrate are fused for efficiency (one recursive pass
|
|
127
|
+
holds both TACO and node), and convenience verbs (mount, append, replace,
|
|
128
|
+
remove, refresh) chain phases — but contain no logic except calls to the
|
|
129
|
+
phase verbs. Each phase has exactly one verb; compounds compose, never
|
|
130
|
+
reimplement. Spec of record: `dev/bitwrench-lifecycle-cleanup-2026-06-09.md`
|
|
131
|
+
(lifecycle) and `dev/bitwrench-css-cleanup-2026-06-09.md` (styling, which
|
|
132
|
+
follows the same grammar: makeStyles=create, applyStyles=mount,
|
|
133
|
+
loadStyles=compound).
|
|
134
|
+
|
|
135
|
+
### 7. Updates are explicit, not reactive
|
|
136
|
+
|
|
137
|
+
Once a component is mounted, there are several clean ways to update it,
|
|
138
|
+
all using pure JS:
|
|
139
|
+
|
|
140
|
+
- **Component methods**: call `el.bw.methodName(args)` -- the component
|
|
141
|
+
updates itself. This is the MFC/Swing model: you tell the component
|
|
142
|
+
what to do, it handles its own DOM. This is the primary and cheapest
|
|
143
|
+
update path.
|
|
144
|
+
- **Slot setters**: auto-generated from `o.slots` -- `el.bw.setTitle('x')`
|
|
145
|
+
replaces content at a cached DOM target. Surgical, O(1).
|
|
146
|
+
- **DOM helpers**: bitwrench provides element finders that resolve by
|
|
147
|
+
reference, CSS selector, or UUID -- with internal caching so repeated
|
|
148
|
+
lookups on known components are cheap.
|
|
149
|
+
- **Pub/sub**: decoupled messaging between components. A component
|
|
150
|
+
subscribes to a topic; when data arrives, its handle method fires.
|
|
151
|
+
Subscriptions auto-clean when the component is removed.
|
|
152
|
+
|
|
153
|
+
bitwrench does NOT do automatic reactivity. There is no dependency
|
|
154
|
+
tracking, no signal subscription graph, no dirty-checking change
|
|
155
|
+
detection. You call a method, it runs, it updates the DOM. Explicitly.
|
|
156
|
+
|
|
157
|
+
**Why not reactive?** Reactive systems solve a real problem: keeping
|
|
158
|
+
UI in sync with state when the developer doesn't know (or doesn't want
|
|
159
|
+
to think about) what changed. The cost is a subscription/proxy/diffing
|
|
160
|
+
layer that must exist between state and DOM.
|
|
161
|
+
|
|
162
|
+
bitwrench's position: for the component scales we target (dozens to low
|
|
163
|
+
hundreds of live components per page), explicit method calls are clearer,
|
|
164
|
+
debuggable, and have zero framework overhead. The component knows exactly
|
|
165
|
+
what changed because the developer told it. No diffing needed.
|
|
166
|
+
|
|
167
|
+
For complex interdependent forms (show B when A is "yes", validate C
|
|
168
|
+
based on B+D), explicit wiring is more code than reactive bindings.
|
|
169
|
+
This is a real cost. The payoff: all the wiring logic is in one place
|
|
170
|
+
(the handle method), visible, debuggable, and produces zero surprise
|
|
171
|
+
re-renders.
|
|
172
|
+
|
|
173
|
+
### 8. Server-driven UI is a first-class capability
|
|
174
|
+
|
|
175
|
+
bwserve lets a server push TACOs to the browser via SSE. The server can
|
|
176
|
+
create, update, replace, and remove UI elements in real time. The client
|
|
177
|
+
renders whatever arrives.
|
|
178
|
+
|
|
179
|
+
Because TACOs are data, any backend language can generate them. A Python
|
|
180
|
+
script, a Go service, or an LLM can produce the JSON; the browser renders
|
|
181
|
+
it. This is closest to Phoenix LiveView, not any JS framework.
|
|
182
|
+
|
|
183
|
+
bwcli extends this to debugging and development. It connects to any
|
|
184
|
+
running web page -- bitwrench-authored or not -- by injecting the
|
|
185
|
+
bitwrench helper library. From there, it can:
|
|
186
|
+
- Inspect the component tree
|
|
187
|
+
- Call component methods
|
|
188
|
+
- Push new UI
|
|
189
|
+
- Listen to events
|
|
190
|
+
- Take screenshots at the page, component, or element level
|
|
191
|
+
|
|
192
|
+
This enables streamlit-style use cases (server-generated data
|
|
193
|
+
visualization), LLM-driven UI (an agent inspects, mutates, screenshots,
|
|
194
|
+
iterates), and remote debugging of production pages.
|
|
195
|
+
|
|
196
|
+
For client-only apps, bitwrench-router (a separate module) provides
|
|
197
|
+
hash/history routing, parameterized routes, guards, and programmatic
|
|
198
|
+
navigation -- all returning TACOs, not managing DOM directly.
|
|
199
|
+
|
|
200
|
+
### 9. Tooling follows from the architecture
|
|
201
|
+
|
|
202
|
+
bitwrench does not need custom browser extensions for inspection (the
|
|
203
|
+
DOM IS the component tree -- querySelector finds everything). It does
|
|
204
|
+
not need a custom profiler (browser DevTools profiles the real DOM,
|
|
205
|
+
not a virtual shadow). It does not need a build step for HMR (there
|
|
206
|
+
is no compiled output to hot-swap -- just re-evaluate the JS).
|
|
207
|
+
|
|
208
|
+
What bitwrench DOES have that other frameworks cannot easily replicate:
|
|
209
|
+
- **Remote inspect + mutate**: connect to a running page over the wire,
|
|
210
|
+
find components, call their methods, change the UI -- no browser
|
|
211
|
+
extension, no local development environment
|
|
212
|
+
- **Remote screenshot**: capture what the page looks like from server
|
|
213
|
+
code, CI, or an LLM -- verify UI state without eyes
|
|
214
|
+
- **LLM-native composition**: an LLM generates JSON, validates against
|
|
215
|
+
a schema, sends it via bwserve, the client renders it. No compiler
|
|
216
|
+
in the loop. No framework-specific AST to generate.
|
|
217
|
+
- **Schema validation across boundaries**: CI validates TACOs without
|
|
218
|
+
running the app. A server validates its output. An LLM validates its
|
|
219
|
+
generation. Teams publish schemas alongside their bwserve endpoints.
|
|
220
|
+
|
|
221
|
+
Standard browser DevTools already cover most inspection and profiling
|
|
222
|
+
ground because the DOM IS the component tree. The machine-driven
|
|
223
|
+
capabilities above (remote inspect, LLM composition, schema validation)
|
|
224
|
+
are structurally trivial here and structurally hard to retrofit onto
|
|
225
|
+
virtual-DOM architectures, where real component state lives in a
|
|
226
|
+
framework-internal shadow tree.
|
|
227
|
+
|
|
228
|
+
### 10. Names carry cost
|
|
229
|
+
|
|
230
|
+
Update operations are ordered by expense:
|
|
231
|
+
|
|
232
|
+
| Operation | Cost |
|
|
233
|
+
|-----------|------|
|
|
234
|
+
| `el.bw.method()`, slot setters | Surgical -- component updates its own DOM |
|
|
235
|
+
| `bw.patch(ref, content)` | Targeted -- updates one element's content |
|
|
236
|
+
| `bw.replace(ref, taco)` | Element swap -- unmounts old, mounts new |
|
|
237
|
+
| `bw.refresh(ref)` | Full rebuild -- tears down and re-renders children |
|
|
238
|
+
|
|
239
|
+
A cheap-sounding verb is never secretly expensive, and no operation
|
|
240
|
+
silently escalates (`bw.update` dispatches or warns -- it never falls
|
|
241
|
+
back to a rebuild). If you can't tell what an operation costs from its
|
|
242
|
+
name, that's a bug in the API.
|
|
243
|
+
|
|
244
|
+
### 11. The registry watches the DOM
|
|
245
|
+
|
|
246
|
+
"The DOM is the registry" cuts both ways: bitwrench must notice when the
|
|
247
|
+
DOM changes underneath it. A document-level MutationObserver (the
|
|
248
|
+
janitor) runs full teardown on any component removed outside bitwrench's
|
|
249
|
+
verbs — hooks fire, registrations clear, subscriptions release. Liveness
|
|
250
|
+
checks at every dispatch mean a dead component never receives a message.
|
|
251
|
+
Nothing bitwrench retains can pin a removed subtree. Rude removal by
|
|
252
|
+
third-party code is an expected event, not an error. The one sanctioned
|
|
253
|
+
exception: `bw.detach(el)` keeps a disconnected element alive and
|
|
254
|
+
registered on purpose -- the exemption clears the moment it reconnects.
|
|
255
|
+
|
|
256
|
+
### 12. Dependencies declared, never tracked
|
|
257
|
+
|
|
258
|
+
bitwrench has no reactive proxies and no auto-tracked dependency graphs
|
|
259
|
+
-- but it does have declared dataflow: `bw.derive(inputTopics, fn,
|
|
260
|
+
outTopic)` recomputes a derived value when its inputs publish. The
|
|
261
|
+
difference from signals is that the graph is written in source where you
|
|
262
|
+
can read it, not assembled by getter traps at runtime. The graph is
|
|
263
|
+
explicit and *disposable* -- every derive returns a stopper and can be
|
|
264
|
+
tied to an element's lifecycle. Derive, the word bitwrench already uses
|
|
265
|
+
for palettes, not useMemo.
|
|
266
|
+
|
|
267
|
+
### 13. Control messages never carry code
|
|
268
|
+
|
|
269
|
+
Servers, CLIs, and LLMs send data: TACOs (structure), verb messages,
|
|
270
|
+
method names, action names (`bw_act_*` classes). Executable code is
|
|
271
|
+
delivered only as page code at page-serving time -- never as later
|
|
272
|
+
protocol payload. (`bw.htmlPage` serializing handler source into the
|
|
273
|
+
page IS code delivery, and it's allowed: serving a page is how web code
|
|
274
|
+
is delivered.) There is no eval verb, no server-registered function
|
|
275
|
+
bodies, and string `on*` attributes are stripped from wire TACOs.
|
|
276
|
+
Interactivity for server-sent UI is the `bw_act_*` class namespace plus
|
|
277
|
+
a client-side delegated dispatcher.
|
|
278
|
+
|
|
279
|
+
### Validation: industry protocol adapters
|
|
280
|
+
|
|
281
|
+
The bitwrench-ag-ui adapter (separate repo, not yet published to npm)
|
|
282
|
+
implements the AG-UI protocol -- a standard for AI agent-to-UI
|
|
283
|
+
communication. AG-UI defines how an AI agent streams events (text
|
|
284
|
+
deltas, tool calls, state updates) to a frontend.
|
|
285
|
+
|
|
286
|
+
agui translates these agent events into bitwrench rendering operations:
|
|
287
|
+
TACO creation, slot updates, component replacement. The adapter is
|
|
288
|
+
~1100 lines with 158 tests and working examples. It is a thin
|
|
289
|
+
translation layer, not a framework. It works because TACOs are data
|
|
290
|
+
(consequence 1), servers can generate them (consequence 2), and the
|
|
291
|
+
client renders whatever arrives (consequence 8).
|
|
292
|
+
|
|
293
|
+
The test: if TACOs required a compiler, if the DOM weren't the
|
|
294
|
+
registry, if updates required a diffing layer, agui would not be a
|
|
295
|
+
thin adapter. It would be a framework.
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## What this means in practice
|
|
300
|
+
|
|
301
|
+
### BCCL: reference component library, not destination
|
|
302
|
+
|
|
303
|
+
bitwrench ships 30+ reference components (BCCL): cards, tables, tabs,
|
|
304
|
+
modals, etc. These provide a batteries-included prototyping experience.
|
|
305
|
+
|
|
306
|
+
BCCL is a reference implementation, not a destination. Large teams build
|
|
307
|
+
their own component libraries on top of bitwrench core (TACO, lifecycle,
|
|
308
|
+
pub/sub, DOM helpers, bwserve). BCCL shows how to write components
|
|
309
|
+
correctly. A company's component library extends the base TACO schema,
|
|
310
|
+
not BCCL's schemas.
|
|
311
|
+
|
|
312
|
+
### Design system from seed colors
|
|
313
|
+
|
|
314
|
+
bitwrench can regenerate an entire design system (colors, spacing,
|
|
315
|
+
typography, elevation, motion) from a handful of seed values. All BCCL
|
|
316
|
+
components consume shared design tokens. A theme that changes colors but
|
|
317
|
+
leaves spacing, shadows, and motion untouched is only half a design
|
|
318
|
+
system.
|
|
319
|
+
|
|
320
|
+
No ad-hoc values. Every component draws from the shared token scales:
|
|
321
|
+
|
|
322
|
+
- **Spacing**: 4, 8, 12, 16, 24, 32, 48 (derived from base unit)
|
|
323
|
+
- **Type ramp**: 12, 14, 16, 18, 20, 24, 30
|
|
324
|
+
- **Color roles**: primary, secondary, surface, muted, error, warning, success, info
|
|
325
|
+
- **Elevation**: sm, md, lg, xl
|
|
326
|
+
- **Motion**: 150ms ease-out (hover), 250ms ease (expand)
|
|
327
|
+
- **Radius**: none, sm, md, lg, pill
|
|
328
|
+
|
|
329
|
+
### Avoid direct DOM manipulation
|
|
330
|
+
|
|
331
|
+
bitwrench provides APIs for every DOM operation a component or example
|
|
332
|
+
should need. If you find yourself writing `document.createElement()`,
|
|
333
|
+
`document.querySelector()`, `innerHTML`, or raw HTML strings -- that is
|
|
334
|
+
drift. The whole point of TACO is that you work with component objects,
|
|
335
|
+
not the DOM directly.
|
|
336
|
+
|
|
337
|
+
**If bitwrench can't do what you need, that's a gap in the API -- fix
|
|
338
|
+
the API, don't work around it.** Ask the maintainer before reaching for
|
|
339
|
+
`document.*`.
|
|
340
|
+
|
|
341
|
+
### Compilation is optimization, not a prerequisite
|
|
342
|
+
|
|
343
|
+
TACO works without a build step. Reactivity comes from the component
|
|
344
|
+
model, not from a compiler. A component's handle method triggers an
|
|
345
|
+
update because the component was built that way, not because a compiler
|
|
346
|
+
wired signal subscriptions. The component model works the same in a
|
|
347
|
+
`<script>` tag and in a bundled production build.
|
|
348
|
+
|
|
349
|
+
A future compile step would add performance optimizations (template
|
|
350
|
+
extraction, dead CSS elimination, pre-rendering). These are performance
|
|
351
|
+
features, not correctness features. A TACO component must work identically
|
|
352
|
+
interpreted and compiled.
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## For reviewers: what to challenge
|
|
357
|
+
|
|
358
|
+
The north star exists so reviewers can test bitwrench's thinking. Here
|
|
359
|
+
are the questions worth pushing on -- and the ones that are already
|
|
360
|
+
answered.
|
|
361
|
+
|
|
362
|
+
### Worth challenging (bitwrench should have good answers)
|
|
363
|
+
|
|
364
|
+
| Challenge | Expected answer |
|
|
365
|
+
|-----------|----------------|
|
|
366
|
+
| "Explicit updates are more code than reactive bindings for complex forms" | Yes. Handle methods colocate the logic (easier to debug). For truly complex cases, build a form component that handles wiring internally. More code, less magic. |
|
|
367
|
+
| "No ecosystem -- where are the 10,000 components?" | Wrap any existing library in a TACO factory. Self-contained JS objects make wrapping trivial. But wrapping still requires effort. |
|
|
368
|
+
| "TACO syntax is ugly compared to JSX" | TACO optimizes for a different developer profile: backend devs, embedded devs, LLM-native devs who think in data structures. JSX optimizes for designers who think in markup. Different tools, different audiences. |
|
|
369
|
+
| "No time-travel debugging, no profiler, no HMR" | Tooling maturity is a function of time, not architecture. Nothing in bitwrench prevents these tools -- the DOM IS the component tree. Meanwhile, machine-driven tooling (remote inspect, LLM composition, schema validation) is structurally trivial here and structurally hard to retrofit onto virtual-DOM frameworks. |
|
|
370
|
+
| "How does this scale to 500+ components on a page?" | Handle methods and slot setters are O(1). Pub/sub dispatch is O(subscribers). Need a benchmark page to verify. Expect it's fine -- the bottleneck is browser layout/paint, not JS dispatch. |
|
|
371
|
+
|
|
372
|
+
### Questions with established answers
|
|
373
|
+
|
|
374
|
+
These have been thought through. Reviewers are welcome to push back,
|
|
375
|
+
but the answers below reflect deliberate design choices, not oversights.
|
|
376
|
+
|
|
377
|
+
| Challenge | Why it's settled |
|
|
378
|
+
|-----------|-----------------|
|
|
379
|
+
| "But React has virtual DOM diffing" | bitwrench doesn't need it. Components update their own DOM directly. No guessing what changed. O(1) per update vs O(tree) diff. |
|
|
380
|
+
| "You need a compiler for reactivity" | No. Reactivity comes from the component model. `el.bw.method()` works because the component was built that way, not because a compiler wired it. |
|
|
381
|
+
| "You need CSS-in-JS libraries" | bitwrench IS CSS-in-JS. Palette objects -> JS functions -> CSS strings. No library needed. |
|
|
382
|
+
| "TypeScript is required for large projects" | bitwrench ships .d.ts. TS is supported, not required. The architecture works without a build step AND with full TS checking. |
|
|
383
|
+
| "How do you handle server rendering?" | bwserve pushes TACOs via SSE. Any backend language generates JSON. The client renders it. This is a first-class capability, not an afterthought. |
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Quick drift checks
|
|
388
|
+
|
|
389
|
+
Before writing code:
|
|
390
|
+
|
|
391
|
+
| Question | If yes | If no |
|
|
392
|
+
|----------|--------|-------|
|
|
393
|
+
| Am I using `document.*` directly? | Drift. Use bitwrench APIs or TACO. | Good. |
|
|
394
|
+
| Am I hardcoding px/rem/hex values? | Drift. Use design tokens. | Good. |
|
|
395
|
+
| Am I putting DOM work in a TACO factory or data path that should stay universal? | Drift. Factories return data; DOM work belongs in hooks/handles. | Good. |
|
|
396
|
+
| Am I writing `<style>` or raw HTML? | Drift. Generate CSS and TACO from JS. | Good. |
|
|
397
|
+
| Am I treating TACO as "nicer innerHTML"? | Drift. It's a component spec. | Good. |
|
|
398
|
+
| Am I reaching for a heavy rebuild when a handle method would do? | Drift. Prefer surgical updates. | Good. |
|
|
399
|
+
| Am I sending code (or function source) over a control channel? | Drift. Send data; use bw_act_* + verbs. | Good. |
|
|
400
|
+
| Am I hand-rolling teardown a verb already does? | Drift. unmount/remove/janitor cover it. | Good. |
|
|
401
|
+
| Am I using `data-bw-*` attributes or hand-typing a `bw_uuid_*`/`bw_lc`/`bw_bccl_*`/`bw_act_*` token? | Drift. bw machine namespaces come from helpers; app-owned `data-*` (e.g. data-testid) is fine. | Good. |
|
|
402
|
+
| Am I retaining a TACO or cloning a DOM node to re-render later? | Drift. Consume once; call the factory again. | Good. |
|
|
403
|
+
| Am I registering anything before mount? | Drift. Registration is mount-to-unmount only. | Good. |
|
|
404
|
+
| Am I moving a live node across an async boundary without `bw.detach`? | Drift. The janitor will reap it. | Good. |
|
|
405
|
+
| Does this component look/feel different from others? | Drift. Check design tokens. | Good. |
|
|
406
|
+
| Would an MFC/Swing developer recognize this pattern? | Good. | Rethink. |
|
|
@@ -150,7 +150,7 @@ bwserve.onMessage = function(msg) {
|
|
|
150
150
|
denyRawHtml: true
|
|
151
151
|
});
|
|
152
152
|
if (!result.valid) return; // reject
|
|
153
|
-
bw.DOM(msg.
|
|
153
|
+
bw.DOM(msg.ref, msg.taco);
|
|
154
154
|
};
|
|
155
155
|
```
|
|
156
156
|
|
|
@@ -475,7 +475,7 @@ Policy merge behavior:
|
|
|
475
475
|
Validate message payloads before `bw.DOM()`/`bw.apply()`:
|
|
476
476
|
|
|
477
477
|
```javascript
|
|
478
|
-
var result = validateTree(msg.
|
|
478
|
+
var result = validateTree(msg.taco, { mode: 'wire', policy: wirePolicy });
|
|
479
479
|
if (!result.valid) {
|
|
480
480
|
// reject payload, log findings, optionally patch an error placeholder
|
|
481
481
|
return;
|