Skip to content

Commit 0c84335

Browse files
authored
docs: polish public docs after alpha.7
docs: polish public docs after alpha.7
2 parents c19c089 + 7aeecad commit 0c84335

7 files changed

Lines changed: 229 additions & 19 deletions

File tree

README.md

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,17 @@ It is not production-ready yet. The goal right now is to keep the foundation sma
3939
Intent is available as experimental alpha packages on npm:
4040

4141
```sh
42-
pnpm add @intent-framework/core@0.1.0-alpha.1 @intent-framework/dom@0.1.0-alpha.1 @intent-framework/router@0.1.0-alpha.1 @intent-framework/testing@0.1.0-alpha.1
42+
pnpm add @intent-framework/core@0.1.0-alpha.7 @intent-framework/dom@0.1.0-alpha.7 @intent-framework/router@0.1.0-alpha.7 @intent-framework/testing@0.1.0-alpha.7
4343
```
4444

4545
```sh
46-
npm install @intent-framework/core@0.1.0-alpha.1 @intent-framework/dom@0.1.0-alpha.1 @intent-framework/router@0.1.0-alpha.1 @intent-framework/testing@0.1.0-alpha.1
46+
npm install @intent-framework/core@0.1.0-alpha.7 @intent-framework/dom@0.1.0-alpha.7 @intent-framework/router@0.1.0-alpha.7 @intent-framework/testing@0.1.0-alpha.7
4747
```
4848

4949
The quickstart pins the current alpha version so examples match the published APIs.
5050

5151
```txt
52-
Current alpha: v0.1.0-alpha.1
52+
Current alpha: v0.1.0-alpha.7
5353
First public alpha: v0.1.0-alpha.0
5454
GitHub Releases: https://github.com/intent-framework/intent/releases
5555
```
@@ -246,9 +246,23 @@ For a guided walkthrough, see [Demo Guide](docs/Demo.md).
246246

247247
For a deep dive into resource semantics — load, reload, invalidation, staleness, and runtime scoping — see the [Resources Guide](docs/Resources.md).
248248

249+
## Examples
250+
251+
The repository includes five runnable examples, each demonstrating a different set of Intent capabilities:
252+
253+
| Example | What it demonstrates |
254+
|---------|---------------------|
255+
| [`canonical-invite`](examples/canonical-invite) | Minimal screen: text ask, primary action, validation, blocked reasons, feedback, `inspectScreen()`. Matches the Quickstart one-to-one. |
256+
| [`choice-form`](examples/choice-form) | All state kinds (text, choice, boolean) and ask kinds (`asChoice()`, `asSecret()`, `hint()`), multiple surfaces per screen, flow diagnostics, full test coverage. |
257+
| [`resource-lifecycle`](examples/resource-lifecycle) | Full resource lifecycle: autoLoad, manual load, reload, invalidation, stale detection, failed state, action-driven invalidation with `.invalidates()`. |
258+
| [`secret-vault`](examples/secret-vault) | Multi-step flows (3+ steps), `asSecret()` + `private()`, `BooleanState` toggles, multi-screen router app, flow diagnostics. |
259+
| [`web-basic`](examples/web-basic) | Multi-screen team invite demo with router, resources, diagnostics panel, feedback, and keyboard default action. |
260+
261+
Each example includes tests. Run with `pnpm dev:<name>` (e.g. `pnpm dev:choice-form`) and test with `pnpm test` from the example directory.
262+
249263
## What the demo demonstrates
250264

251-
The demo is intentionally small. It is a dagger, not a cathedral.
265+
The `web-basic` demo is intentionally small. It is a dagger, not a cathedral.
252266

253267
It demonstrates:
254268

@@ -294,6 +308,9 @@ Diagnostics currently catch graph-level issues such as:
294308
* Primary actions blocked without a human-readable reason
295309
* Asks not included in a surface
296310
* Actions not included in a surface
311+
* Surfaces including nodes that no flow references
312+
* Flow steps referencing nodes not in any surface
313+
* Flows whose steps are entirely disconnected from surfaces
297314

298315
Diagnostics are not lint rules for HTML. They are semantic graph feedback.
299316

@@ -356,6 +373,11 @@ Core rules:
356373

357374
## Roadmap
358375

376+
Completed:
377+
378+
* ✦ Three focused examples: `choice-form`, `resource-lifecycle`, `secret-vault` — covering all state kinds, choice/secret asks, multi-surface screens, resource lifecycle (autoLoad, reload, invalidation, failed state), complex flows, secret+private, and flow diagnostics
379+
* ✦ DOM multi-surface rendering — each surface renders as a semantic `<section>` with surface-suffixed DOM ids, shared state, duplicate controls, and per-surface blocked reasons and feedback
380+
359381
Near-term work:
360382

361383
* Harden the demo path

docs/Quickstart.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ This guide shows the fastest path from zero to a semantic screen using published
77
## 1. Install
88

99
```sh
10-
pnpm add @intent-framework/core@0.1.0-alpha.1 @intent-framework/dom@0.1.0-alpha.1 @intent-framework/testing@0.1.0-alpha.1
10+
pnpm add @intent-framework/core@0.1.0-alpha.7 @intent-framework/dom@0.1.0-alpha.7 @intent-framework/testing@0.1.0-alpha.7
1111
```
1212

1313
Or with npm:
1414

1515
```sh
16-
npm install @intent-framework/core@0.1.0-alpha.1 @intent-framework/dom@0.1.0-alpha.1 @intent-framework/testing@0.1.0-alpha.1
16+
npm install @intent-framework/core@0.1.0-alpha.7 @intent-framework/dom@0.1.0-alpha.7 @intent-framework/testing@0.1.0-alpha.7
1717
```
1818

19-
The quickstart pins `0.1.0-alpha.1` so the examples match the APIs shown below.
19+
The quickstart pins `0.1.0-alpha.7` so the examples match the APIs shown below.
2020

2121
You also need `typescript` and `vitest` for type checking and tests.
2222

docs/Release-Readiness.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Status
44

5-
Three public alpha releases have been published: `0.1.0-alpha.0`, `0.1.0-alpha.1`, and `0.1.0-alpha.2`.
5+
Seven public alpha releases have been published: `0.1.0-alpha.0` through `0.1.0-alpha.7`.
66

77
Five packages are under the `@intent-framework/*` scope, four of which are published to npm. The server package `@intent-framework/server` remains private and unpublished.
88

@@ -29,7 +29,7 @@ Packages under `examples/` (e.g., `web-basic`) are private and must not be publi
2929

3030
| Field | Value | Status |
3131
|---|---|---|
32-
| Current version | `0.1.0-alpha.1` | Acceptable for alpha |
32+
| Current version | `0.1.0-alpha.7` | Acceptable for alpha |
3333
| `main` | `./dist/index.js` | Exists after build |
3434
| `module` | `./dist/index.js` | Exists after build |
3535
| `types` | `./dist/index.d.ts` | Exists after build |
@@ -47,7 +47,7 @@ Packages under `examples/` (e.g., `web-basic`) are private and must not be publi
4747

4848
| Field | Value | Status |
4949
|---|---|---|
50-
| Current version | `0.1.0-alpha.2` | Acceptable for alpha |
50+
| Current version | `0.1.0-alpha.7` | Acceptable for alpha |
5151
| `main` | `./dist/index.js` | Exists after build |
5252
| `module` | `./dist/index.js` | Exists after build |
5353
| `types` | `./dist/index.d.ts` | Exists after build |
@@ -63,7 +63,7 @@ Packages under `examples/` (e.g., `web-basic`) are private and must not be publi
6363

6464
| Field | Value | Status |
6565
|---|---|---|
66-
| Current version | `0.1.0-alpha.1` | Acceptable for alpha |
66+
| Current version | `0.1.0-alpha.7` | Acceptable for alpha |
6767
| `main` | `./dist/index.js` | Exists after build |
6868
| `module` | `./dist/index.js` | Exists after build |
6969
| `types` | `./dist/index.d.ts` | Exists after build |
@@ -79,7 +79,7 @@ Packages under `examples/` (e.g., `web-basic`) are private and must not be publi
7979

8080
| Field | Value | Status |
8181
|---|---|---|
82-
| Current version | `0.1.0-alpha.1` | Acceptable for alpha |
82+
| Current version | `0.1.0-alpha.7` | Acceptable for alpha |
8383
| `main` | `./dist/index.js` | Exists after build |
8484
| `module` | `./dist/index.js` | Exists after build |
8585
| `types` | `./dist/index.d.ts` | Exists after build |
@@ -214,7 +214,7 @@ All post-publish steps use the `NPM_TOKEN` / `NODE_AUTH_TOKEN` from the `npm` en
214214

215215
### Publish cadence
216216

217-
- Currently publishing **alpha releases** (`0.1.0-alpha.0` through `0.1.0-alpha.2` so far)
217+
- Currently publishing **alpha releases** (`0.1.0-alpha.0` through `0.1.0-alpha.7` so far)
218218
- Use `Changesets` pre-release mode for alpha/beta
219219
- Graduate to stable after API surface is settled and real-world usage begins
220220

@@ -273,20 +273,20 @@ Do not manually create GitHub Releases.
273273
- Manual Publish Alpha workflow (manual dispatch only)
274274
- [x] NPM_TOKEN secret added to GitHub repository secrets
275275
- [x] First alpha published (v0.1.0-alpha.0)
276-
- [x] Subsequent alpha releases published (v0.1.0-alpha.1, v0.1.0-alpha.2)
276+
- [x] Subsequent alpha releases published (v0.1.0-alpha.1 through v0.1.0-alpha.7)
277277

278278
## Post-release verification
279279

280280
Published packages (latest alpha):
281281

282-
- `@intent-framework/core@0.1.0-alpha.2`
283-
- `@intent-framework/dom@0.1.0-alpha.3`
284-
- `@intent-framework/router@0.1.0-alpha.2`
285-
- `@intent-framework/testing@0.1.0-alpha.2`
282+
- `@intent-framework/core@0.1.0-alpha.7`
283+
- `@intent-framework/dom@0.1.0-alpha.7`
284+
- `@intent-framework/router@0.1.0-alpha.7`
285+
- `@intent-framework/testing@0.1.0-alpha.7`
286286

287287
Verified:
288288

289-
- npm install smoke test passed for alpha.0, alpha.1, alpha.2
289+
- npm install smoke test passed for alpha.0 through alpha.7
290290
- `alpha` dist-tag points to the latest published alpha version (set by workflow post-publish step)
291291
- `latest` dist-tag points to the latest alpha (changeset behavior — publishes to `latest` when no regular release exists)
292292
- Git tags (`@intent-framework/pkg@version`) are present on remote (pushed by workflow post-publish step)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Resource Lifecycle Example
2+
3+
A focused demonstration of the full resource lifecycle in Intent — autoLoad, manual load, reload, invalidation, stale detection, failed state, and action-driven invalidation.
4+
5+
## What it demonstrates
6+
7+
- Auto-loaded resource that reaches "ready" on screen start
8+
- `autoLoad: false` resource that stays "idle" until explicitly loaded
9+
- `resource.reload()` — transitions through "pending" back to "ready"
10+
- `resource.invalidate()` — marks the resource stale without reloading
11+
- `resource.load()` — manual load for `autoLoad: false` resources
12+
- `.invalidates(resource)` on an action — marks resources stale on success
13+
- Resource "failed" status when a loader throws
14+
- Route-driven resource load context
15+
16+
## Run
17+
18+
```sh
19+
pnpm install
20+
pnpm dev:resource-lifecycle
21+
```
22+
23+
Open the local URL printed by Vite. Use the browser console to inspect resource state.
24+
25+
## Test
26+
27+
```sh
28+
pnpm test
29+
```
30+
31+
Tests cover every resource status transition: autoLoad, idle, pending, ready, stale, failed, and action-driven invalidation.
32+
33+
## Inspect
34+
35+
- Watch the console log for resource load events and load counts
36+
- Each reload increments the team version counter
37+
- The "Broken save" action demonstrates a failed invalidation
38+
- Test file (`src/ResourceDemo.test.ts`) shows the full resource API surface via `@intent-framework/testing`

examples/secret-vault/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Secret Vault Example
2+
3+
A multi-screen password vault application demonstrating complex flows, secret asks with private mode, and flow diagnostics.
4+
5+
## What it demonstrates
6+
7+
- Multi-step `$.flow().startsWith(A).then(B).then(C)` with 3+ steps
8+
- `asSecret()` + `private()` combined — secret data hidden from inspect output
9+
- `asContact("email")` for email input with autocomplete
10+
- `BooleanState` for toggling locked/unlocked view mode
11+
- Flow diagnostics: `surfaced-node-not-in-any-flow` (intentional), no `orphaned-flow` or `flow-step-not-surfaced` in correct config
12+
- `renderRouter()` with 3 screens and navigation between them
13+
- `inspectScreen()` reporting flow `stepCount`
14+
- Keyboard Enter default action in a multi-screen context
15+
16+
## Screens
17+
18+
1. **Login** — username ask + secret password ask + "Unlock vault" primary action. Flow: username → password → unlock.
19+
2. **Vault** — two secret key asks + decrypt/lock actions + `BooleanState` for locked state. Flow: secret key → confirm key → decrypt.
20+
3. **Recovery** — recovery email ask + "Reset vault" with feedback. Flow: email → reset.
21+
22+
## Run
23+
24+
```sh
25+
pnpm install
26+
pnpm dev:secret-vault
27+
```
28+
29+
Open the local URL printed by Vite. Navigate between screens, enter credentials, unlock the vault.
30+
31+
## Test
32+
33+
```sh
34+
pnpm test
35+
```
36+
37+
Tests cover flow step sequencing, secret handling, diagnostics, and full navigation through all 3 screens.
38+
39+
## Compare
40+
41+
For a simpler single-screen example with basic asks and actions, see [`examples/canonical-invite`](../canonical-invite).

examples/web-basic/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Team Invite Demo (web-basic)
2+
3+
A small multi-screen team invite application demonstrating routing, resources, diagnostics, feedback, and keyboard navigation.
4+
5+
## What it demonstrates
6+
7+
- Semantic screens defined without components or JSX
8+
- Typed router navigation with route context
9+
- Runtime-scoped resources with autoLoad and reload
10+
- Ask validation with blocked action reasons
11+
- Feedback output during action execution
12+
- Keyboard Enter default action with accessible hint
13+
- Opt-in screen-name headings
14+
- Graph diagnostics via `inspectScreen()`
15+
16+
## Run
17+
18+
```sh
19+
pnpm install
20+
pnpm dev:web-basic
21+
```
22+
23+
Open the local URL printed by Vite.
24+
25+
## What to inspect
26+
27+
1. Pick a team on the home screen.
28+
2. View team details — resource loads team data from route params.
29+
3. Click **Refresh team** — version increments as the resource reloads.
30+
4. Click **Invite member** — navigate to the invite form.
31+
5. The **Send invite** button is disabled until a valid email is typed.
32+
6. Press **Enter** to submit — the accessible hint appears when the default action is unambiguous.
33+
7. After success, the member count updates automatically.
34+
8. Scroll to the diagnostics panel — `inspectScreen()` output for each screen.
35+
36+
## Walkthrough
37+
38+
For a guided 5-minute demo script, see [docs/Demo.md](../../docs/Demo.md).
39+
40+
For a deep dive into resource semantics, see [docs/Resources.md](../../docs/Resources.md).
41+
42+
## Screens
43+
44+
| Route | Screen | Purpose |
45+
|-------|--------|---------|
46+
| `/` | Home | Team selection |
47+
| `/teams/:teamId` | Team Details | Resource-driven team view |
48+
| `/teams/:teamId/invite` | Invite | Email ask with validation |
49+
| `*` | Not Found | Fallback |

packages/dom/README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,66 @@ npm install @intent-framework/core @intent-framework/dom
2222
- Opt-in screen-name heading via `showScreenName`
2323
- Opt-in semantic data attributes via `showSemanticIds`
2424

25+
## renderDom behavior
26+
27+
### Input types
28+
29+
| Ask kind | Renders as |
30+
|----------|------------|
31+
| `$.state.text()` / default | `<input type="text">` |
32+
| `asContact("email")` | `<input type="email">` with `autocomplete="email"` |
33+
| `asSecret()` | `<input type="password">` |
34+
| `$.state.boolean()` | `<input type="checkbox">` |
35+
| `$.state.choice()` with `asChoice()` | `<select>` with `<option>` elements |
36+
37+
### Boolean and choice asks
38+
39+
Boolean asks render as checkboxes. The checked state is synced with the underlying `BooleanState`.
40+
41+
Choice asks render as `<select>` elements. Options are populated from the `ChoiceState` options array. The selected value is synced with the underlying state.
42+
43+
### Blocked reasons
44+
45+
When an action is disabled due to blocked reasons, the renderer adds:
46+
47+
- `disabled` attribute on the button
48+
- `<p class="intent-blocked-reason" role="alert">` with the first blocked reason text
49+
- `aria-describedby` on the button pointing to the reason element
50+
51+
When the action becomes enabled, the reason element is removed from the DOM and `aria-describedby` is cleared.
52+
53+
### Single-surface output
54+
55+
When a screen has exactly one surface, the output is backward compatible: a single `<main>` element containing one `<form>` with all asks and actions. No surface name suffix is added to DOM ids.
56+
57+
### Multi-surface output
58+
59+
When a screen has multiple surfaces, each surface renders as a separate `<section>` with `aria-label` set to the surface name. Each section contains its own `<form>` with only the items belonging to that surface.
60+
61+
**DOM id suffixes:** All ask inputs, buttons, hint paragraphs, reason paragraphs, and feedback outputs get a `--<surfaceName>` suffix to avoid id collisions.
62+
63+
**Duplicate controls share state:** The same ask appearing in multiple surfaces shares the underlying state. Typing in one surface updates the input in all surfaces.
64+
65+
**Duplicate action buttons:** The same action appearing in multiple surfaces renders separate buttons, all executing the same `executeAct()` call.
66+
67+
**Per-surface feedback:** Each surface gets its own `<output aria-live="polite">` element. Action feedback is updated independently per surface.
68+
69+
**`data-intent-*` semantic ids:** The `data-intent-ask` and `data-intent-action` attributes remain the same across all copies — they identify the semantic node, not the DOM position.
70+
71+
### Enter key default action
72+
73+
When exactly one primary action exists (or exactly one action total), pressing Enter in any text input triggers that action. The Enter hint ("Press Enter to ...") appears reactively when the default action becomes enabled, and is hidden when disabled. Shift/ Meta/ Ctrl/ Alt + Enter are ignored. Enter is ignored on `<textarea>`, `<select>`, and checkbox inputs.
74+
75+
### Options
76+
77+
```ts
78+
renderDom(Screen, {
79+
target: document.getElementById("root")!,
80+
showScreenName: true, // render screen name as <h1>
81+
showSemanticIds: true, // add data-intent-screen, data-intent-ask, data-intent-action attributes
82+
})
83+
```
84+
2585
## Minimal example
2686

2787
```ts

0 commit comments

Comments
 (0)