@loadbare/app 0.18.2 → 0.19.0

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.
Files changed (42) hide show
  1. package/README.md +17 -17
  2. package/dist/build/assemble.d.ts +7 -1
  3. package/dist/build/assemble.d.ts.map +1 -1
  4. package/dist/build/assemble.js +81 -11
  5. package/dist/build/assemble.js.map +1 -1
  6. package/dist/build/cli.d.ts +3 -0
  7. package/dist/build/cli.d.ts.map +1 -1
  8. package/dist/build/cli.js +6 -1
  9. package/dist/build/cli.js.map +1 -1
  10. package/dist/build/declared.d.ts +25 -0
  11. package/dist/build/declared.d.ts.map +1 -0
  12. package/dist/build/declared.js +62 -0
  13. package/dist/build/declared.js.map +1 -0
  14. package/dist/build/pages.d.ts +6 -0
  15. package/dist/build/pages.d.ts.map +1 -1
  16. package/dist/build/pages.js +32 -12
  17. package/dist/build/pages.js.map +1 -1
  18. package/docs/TECHREF-1.0.md +27 -72
  19. package/docs/comparison.md +692 -480
  20. package/docs/departures.md +63 -0
  21. package/docs/miswarts.md +140 -0
  22. package/docs/opinions.md +155 -0
  23. package/docs/reference/builder.md +9 -2
  24. package/docs/reference/chrome.md +2 -1
  25. package/docs/reference/custom-elements.md +1 -1
  26. package/docs/reference/data-binding.md +36 -9
  27. package/docs/reference/page-files.md +36 -4
  28. package/docs/roadmap.md +55 -43
  29. package/docs/testing.md +62 -28
  30. package/docs/theory.md +348 -108
  31. package/package.json +1 -1
  32. package/skills/loadbare-app/SKILL.md +10 -6
  33. package/skills/loadbare-app/references/TECHREF-1.0.md +27 -72
  34. package/skills/loadbare-app/references/builder.md +9 -2
  35. package/skills/loadbare-app/references/chrome.md +2 -1
  36. package/skills/loadbare-app/references/custom-elements.md +1 -1
  37. package/skills/loadbare-app/references/data-binding.md +36 -9
  38. package/skills/loadbare-app/references/miswarts.md +140 -0
  39. package/skills/loadbare-app/references/page-files.md +36 -4
  40. package/docs/possible-ideas.md +0 -314
  41. package/docs/theory-old.md +0 -839
  42. package/docs/what-does-loadbare-extend.md +0 -124
package/docs/theory.md CHANGED
@@ -1,113 +1,353 @@
1
1
  # The Theory of Loadbare/app
2
2
 
3
- Loadbare has multiople opinions, but there are two co-primary drivers
4
- of all design:
5
-
6
- - The user should expect a median round trip of 300ms for server
7
- interactions.
8
- - Elegant abstractions and reimplementations of
9
- browser behavior must be avoided because they threaten
10
- the performance goal, and they introduce accidental
11
- complexity.
12
-
13
- Two early simplifying decisions were that Loadbare would use SQL
14
- terms, and would split server results into two shapes that are
15
- best suited to a UI: a single `row` and a set of `rows`, using
16
- `column` for the value of a single value in a row. Loadbare
17
- does not understand non-atomic column values.
18
-
19
- The framework's job then becomes to support displaying or "landing" values
20
- into the DOM for a given collection of the `row` and `rows` shapes. It
21
- also must provide the three writes, insert, update and delete, plus
22
- an escape hatch for bespoke operations on the server.
23
-
24
- Loadbare implements the following opinions on declarative systems.
25
- - Declarative support for the data shapes and their operations
26
- is easier to reason about for the developer, and greatly reduces
27
- bugs in application code.
28
- - Framework support for declarations about SQL shapes is finite
29
- and free of edge cases, allowing for creation of a robust
30
- framework processor in the browser.
31
-
32
- Other opinions include:
33
- - It would be nice to code straight static HTML, since HTML is
34
- up to the task, being mature and stable. When
35
- custom elements with light DOM are added, any bespoke behavior
36
- can be supported.
37
- - Frameworks should not interfere with CSS
38
- - Code written for loadbare should run reliably on a timeframe
39
- measured in decades. As long as we have browsers, a Loadbare
40
- app should run.
41
-
42
- ## The 300ms Budget
43
-
44
- The first non-negotiable primary goal is a framework where server
45
- round trips can run in a median 300ms, from click to paint.
46
-
47
- Of the 300ms, we allocate 200ms as typical wire time when application
48
- and user are in the same region, leaving 100ms for everything that
49
- happens in the browser, the application server, and the database.
50
-
51
- Since the database's response time is not under the control of the
52
- Loadbare/app framework, we realize Loadbare/app must do its job in as
53
- little time as possible. This is how we arrived at the second
54
- primary opinion of Loadbare/app: to avoid elegant abstractions or
55
- reimplementations of browser behavior that would threaten the
56
- performance goal. Loadbare/app must be thin and get its job done
57
- in low double-digit milliseconds, leaving as much time as possible
58
- to the database and such tasks as authentication or picking up
59
- a connection from the pool.
60
-
61
-
62
- ## Ken Random Thought, For later
63
-
64
- I often wonder if Loadbare/app does not in fact have "low accidental
65
- complexity" but instead has "different accidental complexity".
66
-
67
- Given the inherent complexity of the browser, any comprehensive
68
- solution is going to be non-trivial, so simple measures like vocabulary
69
- size are not good proxies.
70
-
71
- The test, when we put something in, is whether we are following
72
- SQL and following HTML.
73
-
74
- For SQL, we know that we have:
3
+ By Ken Downs
4
+ October 9, 2026
5
+
6
+ The primary goals of Loadbare/app are performance, correctness, and
7
+ developer ergonomics for server-bound applications. These goals motivate
8
+ all design and implementation decisions. The motivations cannot be
9
+ cleanly separated in implementation, they must all be true at once, and
10
+ often overlap and support each other.
11
+
12
+ Correctness: there is precise and perfect integrity between the database
13
+ and the screen as of the last round
14
+ trip. User writes hit the database once. Constraint violations are
15
+ intelligible and rendered in context.
16
+
17
+ Developer ergonomics means the simplest coding path results in an
18
+ application that is correct and performant. Getting the right
19
+ answer painted on the screen must be the lowest friction way to
20
+ write the code. This means many things, but it definitely rules
21
+ out elegant abstractions, excessive boilerplate and housekeeping code.
22
+ It must be difficult to express a solution that is slow or does not
23
+ maintain integrity between database and UI.
24
+
25
+ I admire elegance, but it is very dangerous when it becomes a goal
26
+ for its own sake. An elegant abstraction appeals from its own
27
+ design rather than from what it does for the user: it
28
+ hides the platform instead of mapping onto it, and it must be learned and
29
+ serviced forever.
30
+
31
+ From the user's perspective, performance is an aspect of correctness. A
32
+ slow round trip leaves the user wondering if what they see is correct. The
33
+ ideal user experience is certainty and trust in the application, which
34
+ requires a cumulative experience of an expectation:reward ratio of
35
+ exactly 1:1. All application behaviors that create doubt and
36
+ confusion erode the expectation:reward ratio, and must be removed
37
+ and made difficult to create by construction. A slow application cannot
38
+ provide an expectation:reward ratio of 1:1 because it is constantly
39
+ creating doubt.
40
+
41
+ ## Currency is not a motivator
42
+
43
+ Currency is not a motivator for 1.0.
44
+ By currency, we mean the screen may be updated, absent any action by
45
+ the current user, due to the actions of other users or automated processes.
46
+ The class of apps that require currency are different in kind from those
47
+ that require only correctness. Unprompted updates may even violate
48
+ the Loadbare/app definition of correctness.
49
+
50
+ Currency can be considered when use cases present, and once it is
51
+ reconciled to correctness.
52
+
53
+ ## From motivation to means
54
+
55
+ With the motivations firmly established, everything after is
56
+ technical decisions to establish the means.
57
+
58
+ This can be confusing, because sometimes a means and motivation
59
+ look the same. For example, I personally prefer to code static
60
+ HTML, and would like a data-driven framework that allows that.
61
+ It so happens Loadbare/app works that way. But it would be a
62
+ tedious and unproductive waste of words trying to determine if
63
+ that was a preference, motivation or means.
64
+
65
+ The three primary motivations force all design and implementation
66
+ decisions. All of my other preferences and motivations, such as
67
+ low boilerplate, declarative systems, static HTML and many others
68
+ were all worked in along the way, but always in a way that
69
+ supported the major three motivations.
70
+
71
+ I am happy to say I think it worked. In the sections below,
72
+ you will see how it was done. My own preferences and secondary
73
+ motivations will be plain to see in the decisions, but they
74
+ are always presented as what they are: a means to create a correct
75
+ and performant application with high developer ergonomics.
76
+
77
+ ## The organizing principle
78
+
79
+ Every framework needs an organizing principle that determines implementation
80
+ decisions and the developer experience. For Loadbare/app, a very early
81
+ decision established that principle: Loadbare uses SQL vocabulary and
82
+ understands two SQL data shapes: a `row` or a set of `rows`. We speak
83
+ of rows, columns, keys, insert, update, and delete. We use the word
84
+ "query" when talking about named SQL SELECT statements.
85
+
86
+ Loadbare/app does not understand non-atomic column values. If a
87
+ document is retrieved from a store that embeds child rows into a
88
+ parent row, it must be converted into two separate query results.
89
+
90
+ A relational
91
+ expert will quickly point out that `rows` subsumes `row` and only
92
+ one shape is necessary, but in a UI they are not subsumed. A form
93
+ with its singleton form controls per column is expressed with
94
+ fundamentally different mechanics than a `<ul>`, `<select>` or
95
+ `<table>`. This is a UI framework, not a relational store, so the
96
+ data shapes are optimized for making user interfaces.
97
+
98
+ This one decision serves all three motivations. Two shapes and three
99
+ writes make a small and closed vocabulary, so coding the framework
100
+ is a finite and terminating task. For correctness, a finite task has
101
+ no open-ended edge cases to get wrong, and because every row arrives
102
+ with its key, the screen always knows exactly which row in the
103
+ database it is showing. For performance, every task the framework
104
+ must perform is itself finite, so each one can be measured and
105
+ optimized. For ergonomics, a developer of a database application must
106
+ already know rows, keys, SELECT and DML. Loadbare/app asks them to
107
+ map that knowledge onto HTML, not to learn new concepts.
108
+
109
+ This organizing principle also guards us from creating elegant
110
+ abstractions. Anything new must be a SQL concept, an HTML one, or a
111
+ member of a small, named family of things every browser application
112
+ needs, and an elegant abstraction is none of these. An elegant abstraction works against
113
+ all three motivations at once: it is a place where what the developer
114
+ wrote and what actually happens can drift apart, it adds work to every
115
+ round trip, and it is one more thing to learn and service instead of
116
+ the application. That last cost is where yak-shaving begins.
117
+
118
+ With this decision, Loadbare/app becomes a natural fit for SQL applications,
119
+ and can also be used if back-end data can be formatted to the two
120
+ shapes of `row` and `rows`.
121
+
122
+ ## The performance goal
123
+
124
+ Because performance must be protected at all times, we need to
125
+ get specific about that first. All downstream decisions must know
126
+ the target they are protecting.
127
+
128
+ Research on response time gives two limits. Near 100ms, a response
129
+ feels instantaneous, as if caused directly by the user's action. Near
130
+ one second, the user's flow of thought begins to break (Miller 1968;
131
+ Card, Moran and Newell 1983; Nielsen 1993). Between the two, every
132
+ reduction pays, and the payoff grows sharply below a second (Doherty
133
+ and Thadhani 1982).
134
+
135
+ A server-bound application cannot reach 100ms, because the round trip
136
+ alone takes longer. So Loadbare/app sets its own target: a median of
137
+ 300ms from click to paint, as close to instantaneous as a round trip
138
+ allows, and well inside the limit where doubt begins.
139
+
140
+ With a 300ms budget, we must allocate 200ms as typical wire time
141
+ when an application and user are in the same region, leaving 100ms
142
+ for everything that happens in the browser, the application server,
143
+ and the database.
144
+
145
+ The database's response time is not under the control of
146
+ Loadbare/app, and neither is the application's own server work,
147
+ such as authentication or picking up a connection from the pool.
148
+ So Loadbare/app must be thin, and get its job done in low
149
+ double-digit milliseconds, leaving as much of the 100ms as possible
150
+ to the work that belongs to the application.
151
+
152
+ This is where the organizing principle pays off a second time.
153
+ Having already ruled out elegant abstractions, we extend the rule to
154
+ reimplementations of browser behavior. The browser already parses
155
+ HTML, finds elements by selector, clones templates and manages focus,
156
+ and it does those things in native code faster than any framework
157
+ can do them again in JavaScript. Every millisecond Loadbare/app
158
+ spends redoing the browser's work is a millisecond taken from the
159
+ database.
160
+
161
+ ## The correctness goal
162
+
163
+ Performance has a number, and we can hold a stopwatch to it.
164
+ Correctness has a definition instead, given at the top of this
165
+ document: integrity between database and screen as of the last round
166
+ trip, writes that hit the database once, and constraint violations
167
+ that are intelligible and rendered in context. We protect it by
168
+ making wrong states hard to reach, and by refusing or reporting the
169
+ ones we cannot rule out.
170
+
171
+ The foundation is an observation about data applications. Most
172
+ frameworks support a DOM that is fully mutable at any time for any
173
+ reason. But in a data application, the screen changes for one main
174
+ reason: the server answered with rows. The other changes, such as a
175
+ button waiting on its request, are a small and closed set. So
176
+ Loadbare/app changes the screen only from what the server sent, and
177
+ never ahead of it. There are no optimistic updates, and no guesses
178
+ about what the database probably did.
179
+
180
+ Because every row arrives with its key, the hub matches what arrived
181
+ to what is shown by key, never by position. A row that is gone
182
+ leaves, a row that changed is filled, and a row that did not change
183
+ is left alone, along with anything the user typed into it and has not
184
+ sent. An answer the server could not have meant for the current
185
+ screen is discarded: if the user moved to another page while a
186
+ request was in flight, the write still happened, but its answer does
187
+ not land on a page it says nothing about. When a query answers in a
188
+ shape it did not declare, the page goes without it. A page missing
189
+ one query is better than a page showing the wrong thing.
190
+
191
+ Writes hit the database once because a request comes from the
192
+ document, not from the developer's code. The developer names the
193
+ request, and the hub supplies the query and key from where the
194
+ element sits, so the developer cannot send the wrong key. An element
195
+ whose request is in flight ignores the next click, so a double click
196
+ cannot become a double write.
197
+
198
+ Constraints belong to the database, or to the application's own
199
+ server code. The framework's job is to carry the violation back to
200
+ the user in terms they can act on. A handler refuses a request with
201
+ words written for the user, either for the request as a whole or for
202
+ each column, and the browser shows them on the controls they belong
203
+ to. Anything else that goes wrong on the server reaches the browser
204
+ as a plain failure, so a stack trace or a database message never
205
+ lands in front of a user.
206
+
207
+ Finally, correctness by construction. Whatever can be checked before
208
+ the application runs is checked, and a mistake stops the build or the
209
+ server rather than shipping. The builder refuses a custom element it
210
+ cannot find and any `lb-` attribute the developer is not allowed to
211
+ write. The server refuses, at startup, patterns that are known to be
212
+ wrong, and refuses any request a page did not declare, so the wire
213
+ cannot reach anything the page has not published. What cannot be
214
+ checked ahead of time is reported on the console the moment it
215
+ happens, rather than silently papered over.
216
+
217
+ Each of these removes a source of doubt. Taken together, they are
218
+ how Loadbare/app keeps the expectation:reward ratio at 1:1 from the
219
+ correctness side, as the 300ms budget does from the performance side.
220
+
221
+ ## Guarding the vocabulary
222
+
223
+ A small, clean vocabulary is a means, and it serves ergonomics first.
224
+ Every term a developer must learn that is not about their own
225
+ application is accidental complexity, time spent servicing the tool
226
+ instead of building the app. A messy vocabulary also hurts
227
+ correctness, because overlapping terms create edge cases, and edge
228
+ cases are where the framework and the developer disagree about what
229
+ the code means.
230
+
231
+ With apologies to Brooks and Pike:
232
+
233
+ > Essential complexity should dominate. Show me your abstractions and
234
+ > tooling and I shall remain mystified. Show me your tables and your
235
+ > rendering vocabulary and I shall be enlightened - the organization of
236
+ > the code will be self-evident.
237
+
238
+ A fair critic might say Loadbare/app does not have low accidental
239
+ complexity, only different accidental complexity. I take the
240
+ critique seriously, and it cannot be answered by counting terms. The
241
+ browser is inherently complex, so any complete solution will be
242
+ non-trivial, and vocabulary size alone is not a good proxy. What
243
+ matters more is where the terms come from.
244
+
245
+ Most of the vocabulary comes from SQL, which a developer of a
246
+ database application already knows:
247
+
75
248
  - a `row`, with landing, insert, update, and delete
76
249
  - `rows`, with landing, insert, update, and delete
77
250
 
78
- All of the complexity comes when we map those to HTML, and here again
79
- HTML has a larger surface area but it is still finite.
80
-
81
- If we end up with 'best practices', and they look like accidental
82
- complexity, a bunch of stuff you have to learn, the test is whether
83
- a best practice already exists for HTML or SQL, and whether it makes
84
- sense in the combination.
85
-
86
-
87
- ## LLM-suggested nugget, to be integrated later
88
-
89
- On the critique that Loadbare has "different accidents" than React or
90
- HTMX. Scoped claim:
91
-
92
- > The data vocabulary is SQL data shapes, SELECT and DML applied to
93
- > HTML. It invents no new data concepts. Everything else is a small,
94
- > closed set covering what any browser app needs: navigation, request
95
- > status, and showing what changed between results.
96
-
97
- Supporting points:
98
-
99
- - The developer of a server-bound app must know rows, keys, SELECT and
100
- DML regardless of framework. That knowledge is essential complexity.
101
- Applying it to HTML adds a mapping, not new concepts.
102
- - The same SQL-shape decision that limits the vocabulary keeps the
103
- browser processor finite, which is what fits it in the 300ms budget.
104
- - The non-SQL families today: navigation (`lb-url*`, `lb-path`,
105
- `lb-page*`), request lifecycle (`lb-request-*`), changes between
106
- result sets (`lb-row-live/leaving/moved/changed`, `lb-group-live/leaving`),
107
- and structure (`lb-hub`, `lb-exp-template`, `lb-exp-slot`, `lb-release`).
108
- - The accidents most likely to accumulate are in the mapping rules SQL
109
- does not dictate: which element a row becomes, what a re-landing does,
110
- how a key identifies an element.
111
- - Design rule: a new term must be a SQL concept or belong to a named
112
- family. A new family, or growth in the non-SQL families, is the
113
- signal the critique is starting to land.
251
+ The rest of it comes from HTML, which they also already know.
252
+
253
+ Not everything is SQL or HTML. Any browser application also needs
254
+ navigation, request status, and a way to show what changed between
255
+ one result and the next. These are small, closed families of their
256
+ own. So the rule is that a new term must be a SQL concept, an HTML
257
+ one, or belong to a named family. Any mechanism that is not
258
+ directly serving SQL, HTML or a named family is a mistake and will, sooner
259
+ or later, obstruct progress on the main motivations.
260
+
261
+ The real complexity comes when we map SQL onto HTML. HTML has a
262
+ larger surface area than SQL, but it is still finite. The accidents
263
+ most likely to pile up are in the mapping rules SQL does not dictate:
264
+ which element a row becomes, what happens when a row lands again, and
265
+ how a key identifies an element. That is where to look first when
266
+ the framework starts to feel like something you have to learn.
267
+
268
+ The same test applies to "best practices." If we end up with a list
269
+ of them, and they look like a bunch of stuff you have to learn, we
270
+ ask whether the practice already exists in SQL or HTML, and whether
271
+ it makes sense in the combination. If it does not, it is accidental
272
+ complexity, and the framework should absorb it or drop it.
273
+
274
+ The payoff is that the whole vocabulary fits in one technical
275
+ reference. That means it fits in a developer's head, and in an
276
+ LLM's context window.
277
+
278
+ ## Conclusion
279
+
280
+ Loadbare/app is not for every application. It fits when the data is
281
+ rows, or can easily be shaped into rows, and when user actions
282
+ map to reading and writing those rows. It does not fit an
283
+ application whose data will not take the two shapes, and it does not
284
+ yet fit an application that needs currency. For a database
285
+ application, which describes a great many of the applications
286
+ people actually use at work, I believe it fits very well.
287
+
288
+ These are claims that can be checked. Performance has a
289
+ number: a median round trip of 300ms from click to paint.
290
+ Correctness has a definition: integrity between database and screen
291
+ as of the last round trip, writes that hit the database once, and
292
+ constraint violations rendered in context. The vocabulary has a
293
+ rule: every term is SQL, HTML, or a member of a named family. If
294
+ Loadbare/app misses the number, breaks the definition, or grows past
295
+ the rule, the theory has failed in a way anyone can see.
296
+
297
+ Code written for Loadbare/app should also last. Pages are HTML and
298
+ CSS, widgets are custom elements, the server is Express, and the
299
+ page code is queries against the application's own database. Each
300
+ of those is a standard or a mature tool in its own right, so code
301
+ written today is exposed to very little framework churn tomorrow.
302
+ As long as we have browsers, a Loadbare/app application should run.
303
+
304
+ The same properties matter more now that much code is written by
305
+ LLMs. SQL and HTML are about as well represented in an LLM's
306
+ training as anything can be, and the named families, navigation,
307
+ request status and showing what changed, are concepts every web
308
+ framework has. The model already knows nearly everything, so the
309
+ context we provide only has to spell out the mappings between them.
310
+ That is why the vocabulary fits in one reference, and one reference
311
+ fits in a context window. A framework that refuses mistakes at build time and at
312
+ startup catches the LLM's mistakes along with the developer's. The
313
+ correct application being the easiest one to write is just as true
314
+ when the writer is a model.
315
+
316
+ None of this is new to me. I first wrote this framework in 2003, as
317
+ Andromeda, before Node existed and before we had jQuery. The
318
+ foundation of Andromeda lives on in `@loadbare/db`, which makes the
319
+ data correct by declaring business logic in the schema. The
320
+ conviction behind Andromeda's web layer was that database
321
+ applications deserve a framework built for them. I am just as
322
+ convinced today, and `@loadbare/app` carries that correctness the
323
+ rest of the way, from the database to the paint.
324
+
325
+ So the whole theory comes down to this. Loadbare/app exists to make
326
+ a server-bound application correct, and to deliver that correctness
327
+ fast. The correct, fast application must also be the easiest one to
328
+ write. One early decision, that the framework speaks SQL and
329
+ understands only a `row` and a set of `rows`, serves all three at
330
+ once, and every other decision in this document is a means to the
331
+ same end.
332
+
333
+ ## Appendix: Opinions, Departures and Miswarts
334
+
335
+ In an imperfect world, well defined rules do not always converge to
336
+ perfection. Loadbare/app makes two significant
337
+ [departures](./departures.md) from what this document implies, in
338
+ navigation and on the wire, and a few [miswarts](./miswarts.md)
339
+ appeared during development.
340
+
341
+ The decisions in this document force some positions on the developer.
342
+ They are listed in one place as [opinions](./opinions.md).
343
+
344
+ ## References
345
+
346
+ - Card, S. K., Moran, T. P. and Newell, A. *The Psychology of
347
+ Human-Computer Interaction.* Lawrence Erlbaum, 1983.
348
+ - Doherty, W. J. and Thadhani, A. J. "The Economic Value of Rapid
349
+ Response Time." IBM, November 1982.
350
+ - Miller, R. B. "Response time in man-computer conversational
351
+ transactions." *Proceedings of the AFIPS Fall Joint Computer
352
+ Conference*, 1968.
353
+ - Nielsen, J. *Usability Engineering*, chapter 5. Academic Press, 1993.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loadbare/app",
3
3
  "description": "High performance web app framework for server-bound applications",
4
- "version": "0.18.2",
4
+ "version": "0.19.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -42,8 +42,10 @@ tsc --noEmit
42
42
  `dist/pages.ts` imports page files with their `.ts` extensions, so the
43
43
  application's `tsconfig.json` needs `allowImportingTsExtensions`.
44
44
 
45
- Write, build, fix, and repeat until the build is clean. Then start the
46
- server: `createHub` refuses a page that declares a reserved name at startup,
45
+ Write, build, fix, and repeat until the build is clean. The build loads
46
+ each page's `.queries.ts` and `.requests.ts` to check the names the markup
47
+ carries, so their import-time code runs then; open a database in
48
+ `contextFor`, not at import. Then start the server: `createHub` refuses a page that declares a reserved name at startup,
47
49
  and the server console reports a query that answers with the wrong kind.
48
50
  Restart the server after adding or changing a `.queries.ts` or
49
51
  `.requests.ts` file.
@@ -70,7 +72,8 @@ server.ts
70
72
 
71
73
  The chrome carries `<lb-hub>` inside `<body>`, an empty `<main>` inside the
72
74
  hub, and `<script src="/client.js" defer>`. Everything a user touches sits
73
- inside `<lb-hub>`.
75
+ inside `<lb-hub>`. The chrome belongs to no page, so it names only the
76
+ hub's queries, `lb-url` and `lb-choices`, and sends no declared request.
74
77
 
75
78
  A page is an HTML fragment that lands in `<main>`:
76
79
 
@@ -274,7 +277,9 @@ fetched to be edited is another page, with that row as its master.
274
277
  `crud`, keyed by query name, as `rowInsert`, `rowUpdate` and `rowDelete`.
275
278
  Each works on a `row` query as well as a `rows` query, since the element a
276
279
  `row` lands on carries its key. Every other request name is a declared
277
- request, under `handlers`. Anything undeclared is refused.
280
+ request, under `handlers`. The build refuses markup naming a query or
281
+ request the page does not declare, and the server refuses one that arrives
282
+ anyway.
278
283
 
279
284
  **An empty key is a row not yet entered.** A `row` query answering with an
280
285
  empty key, or a form `--lb-new` pointed, carries `lb-key-value=""`. The hub
@@ -497,6 +502,5 @@ with the package, so no network is needed.
497
502
  library.
498
503
  - [`references/TECHREF-1.0.md`](references/TECHREF-1.0.md) — the reserved
499
504
  names, what a URL names and
500
- [query parms](references/TECHREF-1.0.md#query-parms), and the open items
501
- that block 1.0. Read it before designing around something the other
505
+ [query parms](references/TECHREF-1.0.md#query-parms). Read it before designing around something the other
502
506
  references do not mention.