Skip to content

Commit 57cd900

Browse files
committed
docs(framework): define abstraction ladder
1 parent d99ddb8 commit 57cd900

17 files changed

Lines changed: 811 additions & 153 deletions

‎AGENTS.md‎

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,40 +27,61 @@ root workspace `AGENTS.md` still applies.
2727
- Preserve the core runtime contract: no VDOM, no hidden hydration/diff/rerender
2828
path, no implicit fetches during startup, and no server-only state or cache
2929
contents leaking into browser snapshots.
30-
- Keep Layer 1 and Layer 1.5 understandable without future compiler layers.
31-
L2 or compiler-required work must compile down to the same HTML,
32-
registry, snapshot, server-envelope, route-partial, cache, and boundary
33-
protocol.
30+
- Keep the no-compiler rungs (L0-L3, L5) understandable without future
31+
compiler layers. Compiler-rung work (L4, L6, L7) must compile down to the
32+
same HTML, registry, snapshot, server-envelope, route-partial, cache, and
33+
boundary protocol.
3434

3535
## Framework Shorthand
3636

3737
Use these abbreviations in ADRs, issues, review notes, and Codex prompts:
3838

39-
- `L1`: Layer 1, the no-build browser runtime core. It owns DOM scanning,
40-
attribute prefixes, event binding, signals, command handlers, startup, and the
41-
smallest usable runtime.
42-
- `L1.5`: Layer 1.5, the no-build/low-build server and streaming bridge above
43-
the runtime core. It owns scheduler ordering, async signal settling, SSR
44-
activation, route partials, browser/server cache split, boundary patches,
45-
stream sequencing, and reveal/OOS coordination without requiring a compiler.
46-
- `L2`: Layer 2, the build-required authoring/compiler profile. It owns JSX/TSX
47-
authoring, build adapters, optimizer reports, generated plans, generated
48-
registries, and chunk/manifest decisions that lower onto L1 and L1.5
49-
protocols.
50-
- `NB`: no-build profile. Author HTML and JavaScript run directly with
51-
`Async.start(...)`, default shorthand attributes, and no compiler.
52-
- `BR`: build-required profile. Author JSX/TSX uses imports such as
53-
`@async/framework/jsx`; the compiler/optimizer emits L1/L1.5-compatible
54-
output.
39+
The layer model is the L0-L7 abstraction ladder owned by
40+
`specs/framework/15-abstraction-layers.md`. Rungs are authoring abstractions;
41+
capabilities are protocol properties available from the lowest rung the
42+
protocol allows.
43+
44+
- `L0` Enhance: behavior references on server-owned HTML. Protocol attributes
45+
plus a script tag; native/MPA partial swaps; no app model, build, or client
46+
router.
47+
- `L1` Interpret: the runtime-interpreted app model, no build. Registries,
48+
`Async.use(...)` conventions, scoped fragment components, lifecycle,
49+
scheduler-batched bindings.
50+
- `L2` Bundle: build as delivery plus client routing and an app server.
51+
Bundling must not change protocol semantics; the build stays optional here.
52+
- `L3` SSR: server-rendered component functions with browser activation from
53+
snapshots. No hydration, no rerender. (Not "Resume": resume is the
54+
protocol-wide contract, not a rung.)
55+
- `L4` Transform: JSX/TSX source transforms lowering onto the same protocol,
56+
plus co-located server functions extracted at build time. First rung where
57+
a build is required.
58+
- `L5` Stream: progressive documents; boundary fallback and settling; reveal
59+
ordering; async signals settling server-side. No compiler required.
60+
- `L6` Reorder: out-of-order settling automated by the Optimizer: chunks,
61+
lazy descriptors, generated plans, runtime slices. The OOS protocol itself
62+
is L5-available.
63+
- `L7` Optimize: whole-program compiler
64+
(`specs/framework/16-whole-program-compiler.md`). Specification only.
65+
- Legacy mapping: pre-2026-07 notes use `L1` for rungs L0-L1, `L1.5` for the
66+
server/streaming capability set (now spread across L3 and L5), and `L2` for
67+
the compiler rungs (L4, L6, L7). See the legacy table in
68+
`specs/framework/15-abstraction-layers.md`.
69+
- `NB`: no-build profile, covering rungs L0-L3 and L5. Author HTML and
70+
JavaScript run directly with `Async.start(...)`, default shorthand
71+
attributes, and no compiler.
72+
- `BR`: build-required profile, covering rungs L4, L6, and L7. Author JSX/TSX
73+
uses imports such as `@async/framework/jsx`; the compiler/optimizer emits
74+
protocol-compatible output the no-compiler rungs can speak.
5575
- `OOS`: out-of-order streaming/rendering. Chunks may become ready in a
5676
different order than source order.
5777
- `Suspense`: async boundary ownership for fallback and final content.
5878
- `Reveal`: OOS commit policy for sibling boundaries, such as `as-ready`,
5979
`forwards`, `backwards`, `together`, plus tail visibility.
6080
- `Plan`: generated or virtual framework plan. In BR it is private compiler
6181
plumbing, not a hand-written author API.
62-
- `Optimizer`: the BR compiler pipeline that classifies source, signals,
82+
- `Optimizer`: the L6 BR compiler pipeline that classifies source, signals,
6383
ownership, events, Suspense/Reveal, runtime slices, chunks, and plan output.
84+
Distinct from the deferred L7 whole-program compiler.
6485

6586
## Attribute Example Style
6687

‎README.md‎

Lines changed: 68 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ Async.start({ root: document });
4343

4444
## What It Is
4545

46-
`@async/framework` is the L1 runtime plus the first L1.5 app/server and
46+
`@async/framework` ships the no-compiler rungs of the abstraction ladder
47+
(L0-L3, L5): the browser runtime, app/server integration, SSR activation, and
4748
streaming primitives. It keeps the runtime small and explicit:
4849

49-
- No build step for L1 consumers.
50+
- No build step on the no-compiler rungs.
5051
- No virtual DOM, diff path, hydration runtime, or component rerender loop.
5152
- Signals are the state boundary.
5253
- `Async.use(...)` registers app declarations before or after startup.
@@ -59,23 +60,41 @@ streaming primitives. It keeps the runtime small and explicit:
5960
- Boundaries can be swapped out of order and rescanned, which keeps server
6061
streaming and partial HTML replacement simple.
6162

62-
Higher layers can add JSX lowering, TypeScript, chunk manifests, compiler-owned
63-
server/client splits, and intent-first authoring later. They should compile down
64-
to the same runtime registries and HTML protocol.
63+
The compiler rungs (L4 Transform, L6 Reorder, L7 Optimize) add JSX lowering,
64+
TypeScript, chunk manifests, compiler-owned server/client splits, and
65+
intent-first authoring. They compile down to the same runtime registries and
66+
HTML protocol.
6567

6668
## Layers
6769

68-
Async is designed as layers, so each level can stay useful without forcing the
69-
next level on every app.
70-
71-
| Shorthand | Name | Requirement | Purpose |
72-
| --- | --- | --- | --- |
73-
| L1 | Runtime bootloader | No build. CDN or direct ESM import. | Signals, async signals, scheduler, handlers, command events, lifecycle pseudo-events, scoped fragments, and boundary swaps. |
74-
| L1.5 | App/server and streaming bridge | Light server integration. No app compiler required. | `Async.use(...)`, router modes, server function proxy, partial declarations, SSR output, browser activation, split browser/server cache, and streamed boundary patches. |
75-
| L2 | Build-required authoring and compiler profile | Build step required. | JSX, ESM, and TypeScript authoring, optimizer reports, generated plans, generated registries, chunks, manifests, and future resumability records that lower onto L1 and L1.5 protocols. |
76-
77-
The package in this repository intentionally focuses on L1 and L1.5. L2 is a
78-
higher authoring surface, not an extra runtime requirement for plain HTML apps.
70+
Async's layer model is an abstraction ladder. Each rung is anchored to an era
71+
of framework history and named by the abstraction it adds between the author
72+
and the runtime protocol. Rungs are authoring abstractions; capabilities are
73+
protocol properties that land at the lowest rung the protocol allows.
74+
75+
| Rung | Name | Era anchor | Adds | Requires |
76+
| --- | --- | --- | --- | --- |
77+
| L0 | Enhance | jQuery/Backbone; htmx | Behavior references on server-owned HTML | Script tag |
78+
| L1 | Interpret | angular.js: runtime, no build | Runtime-interpreted app model: registries, components, lifecycle | Script tag or ESM |
79+
| L2 | Bundle | Built SPAs | Build as delivery, client routing, app server | Build optional |
80+
| L3 | SSR | React-without-JSX + SSR server | Server-rendered components with activation, no hydration | Server; build optional |
81+
| L4 | Transform | React+JSX; Qwik-style `server$` | JSX/TSX transforms, co-located server functions | Build |
82+
| L5 | Stream | Streaming SSR; Suspense | Progressive documents, boundary reveal ordering | Streaming server |
83+
| L6 | Reorder | RSC; islands | Out-of-order settling automated by the Optimizer | Optimizer |
84+
| L7 | Optimize | React Compiler; TSRX | Whole-program compilation | Spec only today |
85+
86+
Because capabilities are protocol properties, they arrive earlier than their
87+
era anchors did: out-of-order streaming works from a no-build CDN script (L5
88+
protocol; L6 only automates it), SSR activates without hydration at L3, and
89+
server functions are callable from L0 through explicit envelopes. Rungs also
90+
compose within one document — an L2-bundled SPA can host an L0-enhanced form
91+
next to an L5-streamed boundary — and patterns like islands are rung
92+
combinations, not rungs.
93+
94+
This package ships the no-compiler rungs (L0-L3, L5) plus the first
95+
compiler-rung surfaces (`./jsx`, `./vite`, `./runtime/*`). The owning
96+
contract is
97+
[specs/framework/15-abstraction-layers.md](./specs/framework/15-abstraction-layers.md).
7998

8099
## Install
81100

@@ -88,9 +107,10 @@ and package lifecycle tooling. Browser consumers import ESM directly.
88107

89108
## Vite And Hono
90109

91-
The Vite entry can run a Hono app as the local development server while keeping
92-
the browser runtime at L1. Install the optional Hono dev packages in apps that
93-
use this profile:
110+
The Vite entry can run a Hono app as the local development server while the
111+
browser stays on the no-build runtime (L1 Interpret; the build is L2 Bundle
112+
delivery). Install the optional Hono dev packages in apps that use this
113+
profile:
94114

95115
```bash
96116
pnpm add hono
@@ -105,7 +125,6 @@ import { asyncFramework } from "@async/framework/vite";
105125
export default defineConfig({
106126
plugins: [
107127
asyncFramework({
108-
layer: 1,
109128
server: {
110129
entry: "src/server.js"
111130
},
@@ -118,6 +137,15 @@ export default defineConfig({
118137
});
119138
```
120139

140+
`asyncFramework(...)` declares needs, not ladder positions: entries declare
141+
render targets (`server.entry` selects the server lane, `client.entry` the
142+
browser build lane), and transforms are detected from imports — `.jsx`/`.tsx`
143+
modules importing `@async/framework/jsx` opt into the JSX bootstrap (L4). The
144+
legacy `layer` option only annotates the build report; it is scheduled for
145+
replacement by the needs-based config in
146+
[specs/framework/15-abstraction-layers.md](./specs/framework/15-abstraction-layers.md),
147+
so omit it.
148+
121149
During local development, run Vite:
122150

123151
```json
@@ -155,7 +183,7 @@ app.get("/", (context) => {
155183
export default app;
156184
```
157185

158-
The client entry stays ordinary L1 framework code:
186+
The client entry stays ordinary no-build runtime code:
159187

160188
```js
161189
// src/client.js
@@ -214,10 +242,10 @@ production:
214242
| `browser.min.js` | ESM | Compact browser module bundle |
215243
| `browser.umd.js` | UMD | Readable script-tag/CommonJS-style bundle |
216244
| `browser.umd.min.js` | UMD | Compact script-tag/CommonJS-style bundle and default CDN file |
217-
| `browser.ts` | Bundled browser TypeScript source | TS-aware runtimes and higher-layer tooling |
245+
| `browser.ts` | Bundled browser TypeScript source | TS-aware runtimes and compiler-rung tooling |
218246
| `browser.d.ts` | Type declarations | TypeScript declarations for the browser API |
219247
| `server.js` | ESM | Server-capable Node.js bundle |
220-
| `framework.ts` | Bundled server-capable TypeScript source | TS-aware runtimes and higher-layer tooling |
248+
| `framework.ts` | Bundled server-capable TypeScript source | TS-aware runtimes and compiler-rung tooling |
221249
| `framework.d.ts` | Type declarations | TypeScript declarations for the server-capable API |
222250

223251
```html
@@ -304,8 +332,9 @@ You can also use an import map so app code imports `@async/framework` by name:
304332

305333
## Advanced Build-Step Runtime
306334

307-
Layer 1 still works with no build step. A build step can optimize the same
308-
runtime by emitting SSR HTML plus compact registry descriptors. The browser can
335+
The no-build rungs keep working without a build step. A build step can
336+
optimize the same runtime by emitting SSR HTML plus compact registry
337+
descriptors. The browser can
309338
start in the document head, apply snapshots, and wait for a root to appear:
310339

311340
```html
@@ -409,8 +438,8 @@ For declarative async boundaries, use `<async-suspense>` or keep using
409438
</async-suspense>
410439
```
411440

412-
The build layer can hide `createBoundaryReceiver(...)` setup, but streaming is
413-
still explicit boundary patches: boundary id, sequence number, HTML, signal
441+
The compiler rungs can hide `createBoundaryReceiver(...)` setup, but streaming
442+
is still explicit boundary patches: boundary id, sequence number, HTML, signal
414443
patches, and browser-cache patches. Async does not ship a component resume graph.
415444

416445
## Core API
@@ -658,8 +687,8 @@ signals.set("product.title", "Headphones");
658687

659688
### Scheduler
660689

661-
The scheduler is the Layer 1.5 ordering engine. Signal writes are still
662-
synchronous:
690+
The scheduler is the runtime ordering engine behind bindings, SSR activation,
691+
and streaming. Signal writes are still synchronous:
663692

664693
```js
665694
signals.set("count", 3);
@@ -696,7 +725,7 @@ await scheduler.flush();
696725
```
697726

698727
Most apps do not need to call the scheduler directly. It is exposed for tests,
699-
custom runtimes, streaming receivers, and higher layers that need explicit flush
728+
custom runtimes, streaming receivers, and higher rungs that need explicit flush
700729
boundaries.
701730

702731
### Async Signals
@@ -1024,7 +1053,7 @@ For app code, register routes and partials through the app registry:
10241053
- `Async.use({ route, partial })` plus `Async.start({ mode, boundary })` for app
10251054
hub setup.
10261055

1027-
Most apps should start at that layer and only move down when they need a more
1056+
Most apps should start at that level and only move down when they need a more
10281057
specific routing shape:
10291058

10301059
| If the app is doing this | Use this pattern |
@@ -1811,28 +1840,30 @@ then runs release doctor.
18111840
18121841
## Status
18131842
1814-
The core runtime is intentionally small. Build-required JSX has optimizer
1843+
The core runtime is intentionally small. Build-required JSX (L4) has optimizer
18151844
artifacts for event, signal, stream, and children-fragment lowering, while full
18161845
compiler emission, lazy chunk manifests, TSRX lowering, server resource
1817-
compilation, and higher-level resumability metadata remain later layers. See
1846+
compilation, and higher-level resumability metadata remain compiler-rung work
1847+
(L6 and L7). See
18181848
`specs/framework/12-composition-patterns.md` for composition pattern guidance
18191849
and planned source forms.
18201850
18211851
## Async And htmx
18221852
18231853
Async and htmx are both HTML-first and avoid a virtual DOM, but they optimize
1824-
for different boundaries.
1854+
for different boundaries. In ladder terms, htmx-style hypermedia is the L0
1855+
Enhance rung — and in Async it stays available at every rung above.
18251856
18261857
| Area | htmx | Async |
18271858
| --- | --- | --- |
18281859
| Primary model | HTML attributes issue HTTP requests and swap server responses. | HTML attributes bind signals, command events, server calls, and route boundaries. |
18291860
| State | Server-owned hypermedia state; browser state is intentionally minimal. | Browser signal registry plus server signal patches and cache snapshots. |
18301861
| Server interaction | DOM attributes describe HTTP verbs, targets, and swaps. | `server.*(...)` commands call registered server functions and apply returned effects. |
18311862
| Routing | Usually server navigation or htmx-boosted navigation. | CSR, SPA, SSR, SSR-SPA, and MPA router modes built around partial boundaries. |
1832-
| Components | Server-rendered HTML fragments. | Scoped fragment functions today; higher layers can compile JSX/TSRX later. |
1833-
| Build story | No build by default. | Layer 1 is no-build/CDN; higher layers can add build or compiler steps. |
1863+
| Components | Server-rendered HTML fragments. | Scoped fragment functions today; the compiler rungs add JSX/TSRX authoring. |
1864+
| Build story | No build by default. | Rungs L0-L3 and L5 are no-build/CDN; the compiler rungs (L4, L6, L7) add build or compiler steps. |
18341865
18351866
Use htmx when the server should own most interaction through hypermedia and
18361867
HTTP swaps. Use Async when you want an HTML-first runtime that also has local
18371868
signals, async resources, registered browser/server handlers, route partials,
1838-
and a path to higher compiler layers without changing the Layer 1 protocol.
1869+
and a path up the compiler rungs without changing the protocol.

‎docs/build/profile.md‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Build Profile
22

3-
The build-required profile adds JSX, TypeScript, optimizer reports, and framework plans while preserving the L1 and L1.5 runtime contracts.
3+
The build-required profile covers the compiler rungs of the abstraction ladder: L4 Transform (JSX, TypeScript) and L6 Reorder (optimizer reports, framework plans, runtime slices). It preserves the no-compiler runtime contracts (rungs L0-L3, L5) — see the [Layers guide](#/docs/layers).
44

55
## JSX entrypoints
66

@@ -41,6 +41,15 @@ The optimizer classifies source inventory, signal ownership, event syntax, child
4141

4242
Each selected runtime slice carries a `status`: `available` slices (`signals`, `events`) activate through `@async/framework/runtime` today, while `planned` slices (`async-signals`, `stream`) are recorded in the report — with a `runtime-slice-planned` warning diagnostic — until their runtime entrypoints ship.
4343

44+
## Vite plugin config
45+
46+
`asyncFramework(...)` declares needs, not ladder positions:
47+
48+
- `server.entry` selects the server lane. The plugin composes the Hono dev server; the app owns the HTML shell, SSR, and streaming.
49+
- `client.entry` selects the browser build lane.
50+
- The JSX bootstrap is detected from imports of `@async/framework/jsx` in `.jsx`/`.tsx` modules; there is no transform switch to set.
51+
- The legacy `layer` option only annotates the build report and is scheduled for replacement by the needs-based config in `specs/framework/15-abstraction-layers.md`; omit it.
52+
4453
## Current boundary
4554

46-
The package includes the runtime, server bridge, JSX profile types, and Vite profile helpers. The optimizer consumes a fixture profile (`asyncFramework({ fixture })`); source-derived profile generation, full compiler emission, lazy chunk manifests, TSRX lowering, boundary activation for `planned` slices, and higher-level resume metadata remain later layers.
55+
The package includes the runtime, server bridge, JSX profile types, and Vite profile helpers. The optimizer consumes a fixture profile (`asyncFramework({ fixture })`); source-derived profile generation, full compiler emission, lazy chunk manifests, TSRX lowering, boundary activation for `planned` slices, and higher-level resume metadata remain later compiler-rung work (L6, and L7 per `specs/framework/16-whole-program-compiler.md`).

‎docs/nav.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"pages": [
1717
{ "title": "Getting Started", "route": "/docs/getting-started", "source": "start/getting-started.md" },
1818
{ "title": "Why Async", "route": "/docs/why-async", "source": "start/why-async.md" },
19-
{ "title": "Core Concepts", "route": "/docs/core-concepts", "source": "start/core-concepts.md" }
19+
{ "title": "Core Concepts", "route": "/docs/core-concepts", "source": "start/core-concepts.md" },
20+
{ "title": "Layers", "route": "/docs/layers", "source": "start/layers.md" }
2021
]
2122
},
2223
{

0 commit comments

Comments
 (0)