@cs4alhaider/screenbook 0.1.0 → 0.2.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/AGENTS.md +147 -0
- package/CLAUDE.md +4 -184
- package/README.md +146 -163
- package/bridge.js +16 -2
- package/cli/postinstall.js +34 -0
- package/cli/screenbook.js +84 -34
- package/cli/templates.js +54 -1
- package/core/browser.js +22 -7
- package/core/project.js +28 -7
- package/core/serve.js +22 -7
- package/docs/README.md +25 -14
- package/docs/brand/logo-mark.png +0 -0
- package/docs/brand/logo-transparent.png +0 -0
- package/docs/brand/logo.png +0 -0
- package/docs/brand/readme-header.png +0 -0
- package/docs/contributing/architecture.md +153 -0
- package/{TESTING.md → docs/contributing/testing.md} +13 -8
- package/docs/{app-mode-guide.md → guides/app-mode.md} +17 -10
- package/docs/{authoring-guide.md → guides/authoring.md} +43 -17
- package/docs/guides/getting-started.md +84 -0
- package/docs/{studio-guide.md → guides/studio.md} +3 -2
- package/docs/{troubleshooting.md → guides/troubleshooting.md} +11 -8
- package/docs/{cli.md → reference/cli.md} +15 -10
- package/docs/{mcp-agents.md → reference/mcp-agents.md} +3 -3
- package/docs/shots/android-dark.png +0 -0
- package/docs/shots/android-light.png +0 -0
- package/docs/shots/app-mode-dark.png +0 -0
- package/docs/shots/app-mode-light.png +0 -0
- package/docs/shots/hero-studio-dark.png +0 -0
- package/docs/shots/hero-studio-light.png +0 -0
- package/docs/shots/review-mode-dark.png +0 -0
- package/docs/shots/review-mode-light.png +0 -0
- package/docs/shots/rtl-arabic-dark.png +0 -0
- package/docs/shots/rtl-arabic-light.png +0 -0
- package/docs/shots/theme-lab-dark.png +0 -0
- package/docs/shots/theme-lab-light.png +0 -0
- package/docs/shots/theming-noir-dark.png +0 -0
- package/docs/shots/theming-noir-light.png +0 -0
- package/docs/shots/web-dashboard-dark.png +0 -0
- package/docs/shots/web-dashboard-light.png +0 -0
- package/examples/qahwa/features/order/screens/010-menu.html +1 -1
- package/examples/qahwa/features/order/screens/020-drink.html +1 -1
- package/examples/qahwa/features/order/screens/030-cart.html +1 -1
- package/examples/qahwa/features/order/screens/040-status.html +1 -1
- package/examples/qahwa/features/order/screens/050-status-android.html +1 -1
- package/examples/qahwa/features/roastery/screens/010-orders.html +1 -1
- package/examples/qahwa/features/roastery/screens/020-menu-editor.html +1 -1
- package/examples/spa-demo/app/index.html +1 -1
- package/examples/tokens-lab/features/lab/screens/010-swatches.html +1 -1
- package/examples/tokens-lab/features/lab/screens/020-typography.html +1 -1
- package/mcp/server.js +4 -2
- package/package.json +7 -6
- package/shell/screenhost.js +4 -1
- package/shell/selftest.js +18 -2
- package/shell/shell.css +17 -9
- package/shell/store.js +2 -0
- package/skill/SKILL.md +1 -1
- package/skill/references/cli-mcp.md +1 -1
- package/skill/references/screen-contract.md +1 -1
- package/docs/getting-started.md +0 -88
- package/docs/shots/app-mode.png +0 -0
- package/docs/shots/hero-studio.png +0 -0
- package/docs/shots/rtl-arabic.png +0 -0
- package/docs/shots/theme-lab.png +0 -0
- package/docs/shots/theming-noir.png +0 -0
- package/docs/shots/web-dashboard.png +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Architecture — how the engine works
|
|
2
|
+
|
|
3
|
+
One mental model: **two worlds meeting at plain files.**
|
|
4
|
+
|
|
5
|
+
- **The studio** runs in the browser — plain ES modules, zero dependencies, no build step.
|
|
6
|
+
It reads the project's JSON + HTML over HTTP and renders screens in iframes.
|
|
7
|
+
- **The tooling** runs in Node — the CLI and the MCP server, sharing one core. Exactly one
|
|
8
|
+
dependency (`playwright-core`), used only for headless validation and screenshots.
|
|
9
|
+
|
|
10
|
+
Nothing is generated, bundled, or transpiled. What's in the repo is what executes.
|
|
11
|
+
|
|
12
|
+
## Repo map
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
bridge.js the ONLY file a screen includes — Engine API + sb:* protocol + EngineKit
|
|
16
|
+
app-bridge.js runs inside an embedded SPA — AppBridge API + sba:* protocol
|
|
17
|
+
index.html the studio page (loads shell/main.js)
|
|
18
|
+
shell/ the studio, one module per concern (see below)
|
|
19
|
+
core/ Node core shared by CLI + MCP: fs, meta, project API, server, browser
|
|
20
|
+
cli/screenbook.js command dispatcher: init · serve · manifest · validate · screenshot · app · mcp
|
|
21
|
+
cli/templates.js everything `init` scaffolds into a fresh project
|
|
22
|
+
mcp/server.js stdio JSON-RPC MCP server — 18 tools over the same core
|
|
23
|
+
skill/ the agent skill `init` copies into consumer projects
|
|
24
|
+
examples/ runnable demo projects that double as test fixtures
|
|
25
|
+
test/ the engine's own suite (node:test) — see the testing map
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## The bridge (`bridge.js`)
|
|
29
|
+
|
|
30
|
+
A screen is a standalone HTML document whose only obligation is a meta block and one
|
|
31
|
+
script include: the bridge. It boots in one of two modes:
|
|
32
|
+
|
|
33
|
+
- **Embedded** — the screen is inside the studio's iframe. The bridge sends `sb:hello`,
|
|
34
|
+
the shell answers `sb:init` with everything the screen needs (theme, mode, dir, lang,
|
|
35
|
+
merged data, i18n, review pins). Live changes arrive as `sb:update` / `sb:review`.
|
|
36
|
+
- **Standalone** — the screen was opened directly. The bridge self-loads
|
|
37
|
+
`app.config.json`, the theme, seed + scenarios, and i18n from their conventional
|
|
38
|
+
relative paths, honoring `?scenario=…&mode=dark&dir=rtl&lang=…` — so a screen file is
|
|
39
|
+
demoable with zero infrastructure. If an `sb:hello` goes unanswered for 600ms (iframed
|
|
40
|
+
by something that isn't the shell), it falls back to standalone.
|
|
41
|
+
|
|
42
|
+
The top half of the file is **EngineKit** — the pure logic both worlds must agree on:
|
|
43
|
+
deep merge, scenario overlay (`remove` dot-paths, then `patch`), `{{today±N}}` date
|
|
44
|
+
tokens, token flattening (`color.ink-2` → `--color-ink-2`), dark-over-light theme
|
|
45
|
+
resolution, i18n lookup, and the CSS-path builder for review pins. The shell loads
|
|
46
|
+
`bridge.js` too (with `window.__SCREENBOOK_SHELL__` set) purely to reuse this kit — the
|
|
47
|
+
merge/flatten/date logic exists exactly once. The Node unit tests load the same file in a
|
|
48
|
+
VM, so the browser and the tests exercise identical code.
|
|
49
|
+
|
|
50
|
+
What screens see: `Engine.ready(cb)` · `Engine.data` (frozen) · `Engine.env` ·
|
|
51
|
+
`Engine.state` (localStorage-backed KV that syncs across screens via `storage` events) ·
|
|
52
|
+
`Engine.go` / `data-go` · `Engine.t` · `Engine.toast`.
|
|
53
|
+
|
|
54
|
+
## The shell (`shell/`)
|
|
55
|
+
|
|
56
|
+
A tiny unidirectional loop, no framework:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
store.js → set(patch) → subscribers get the set of changed keys → each module
|
|
60
|
+
re-renders only what its keys touch → syncHash() mirrors state to the URL
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
| Module | Owns |
|
|
64
|
+
|--------|------|
|
|
65
|
+
| `store.js` | UI state, selectors, hash deep links (`#feature/screen?scenario=…&mode=…`) |
|
|
66
|
+
| `net.js` | project loading (config, features, themes), serve detection, SSE, review persistence |
|
|
67
|
+
| `main.js` | boot, toolbar wiring, keyboard, live reload, the change→render map |
|
|
68
|
+
| `screenhost.js` | the mounted iframe: builds frames, speaks sb:*/sba:*, pushes env updates |
|
|
69
|
+
| `frames.js` | device chrome (iPhone island/status bar, Android punch-hole, browser bar) + scale-to-fit |
|
|
70
|
+
| `sidebar.js` | searchable, grouped screen list |
|
|
71
|
+
| `toolbar.js` | dropdown/toggle/action chip widgets |
|
|
72
|
+
| `flowplayer.js` | walkthrough playback; steps can pin scenarios; restores state on exit |
|
|
73
|
+
| `review.js` | pins, the comments panel, disk/localStorage persistence |
|
|
74
|
+
| `themelab.js` | live token editing; dark stays a delta; save writes `themes/<id>.json` |
|
|
75
|
+
| `selftest.js` | the in-browser render matrix (below) |
|
|
76
|
+
|
|
77
|
+
Two decisions carry most of the weight here. **Screens live in iframes** — full style and
|
|
78
|
+
error isolation, which is what lets the gate say "zero console errors" and mean it. And
|
|
79
|
+
**state changes are described, not performed** — `set({mode:'dark'})` doesn't touch the
|
|
80
|
+
DOM; every interested module reacts, which is why deep links, flows, and the self-test can
|
|
81
|
+
drive the studio through the same door the toolbar uses.
|
|
82
|
+
|
|
83
|
+
## App mode (`app-bridge.js`)
|
|
84
|
+
|
|
85
|
+
An embedded SPA mounts once and is *driven* over `sba:*` instead of being remounted per
|
|
86
|
+
screen. The adapter (`screens()`, `go()`, optional `current()`/`set()`/`scenarios()`)
|
|
87
|
+
gets registered in one of two ways: **cooperative** — the app includes `app-bridge.js`
|
|
88
|
+
itself; **driven** — the shell injects the runtime plus a project-owned `driver.js` into
|
|
89
|
+
the (same-origin) iframe after load, so the app's own files stay byte-untouched.
|
|
90
|
+
|
|
91
|
+
## The Node core (`core/`)
|
|
92
|
+
|
|
93
|
+
| Module | Owns |
|
|
94
|
+
|--------|------|
|
|
95
|
+
| `fsx.js` | atomic writes (temp + rename), change-detecting JSON writes — every CLI/MCP write goes through here |
|
|
96
|
+
| `meta.js` | the screen-meta block: parse, rewrite, `updated` stamping, the screen lint, `data-go` extraction |
|
|
97
|
+
| `project.js` | **the one Project API** both CLI and MCP import: root resolution, feature scan, derived manifests, screen CRUD with lint-on-write, data/theme/flow/comment accessors, static validation |
|
|
98
|
+
| `serve.js` | the dev server: project root + `/screenbook/*` package mount + `/project/*` parent mount, no-cache everywhere, SSE live reload, watch → debounced manifest regen, review/theme write-back APIs |
|
|
99
|
+
| `browser.js` | headless side: playwright→system-Chrome resolution ladder (auto-download as last resort), the headless self-test wrapper, framed screenshots via the shell's `?solo=1` |
|
|
100
|
+
|
|
101
|
+
The CLI and the MCP server are both **thin faces over `project.js`** — same validation,
|
|
102
|
+
same atomic writes, same manifest regeneration, whether a human or an agent is typing.
|
|
103
|
+
`manifest.json` is always derived from the screens' meta blocks; it exists so the studio
|
|
104
|
+
can boot on any dumb static server, but the CLI/MCP/serve regenerate it — never edit it.
|
|
105
|
+
|
|
106
|
+
## The gate (`selftest.js` + `validate`)
|
|
107
|
+
|
|
108
|
+
`?selftest=1` renders **every screen × device variant × theme × light/dark × LTR/RTL** in
|
|
109
|
+
hidden iframes (a small worker pool), replaying the exact shell handshake per combo, and
|
|
110
|
+
requires `Engine.ready` + a meta title + zero console errors. Embedded apps must register
|
|
111
|
+
within 20s, report ≥1 screen, and survive a visit to every screen they report.
|
|
112
|
+
`screenbook validate` = static checks from `project.js` first, then this same matrix run
|
|
113
|
+
headlessly, with results read off `window.__selftestResult`. Green is the definition of
|
|
114
|
+
done — for humans and agents alike.
|
|
115
|
+
|
|
116
|
+
## The protocols
|
|
117
|
+
|
|
118
|
+
| Message | Direction | Meaning |
|
|
119
|
+
|---------|-----------|---------|
|
|
120
|
+
| `sb:hello` | screen → shell | bridge booted; carries the parsed meta |
|
|
121
|
+
| `sb:init` | shell → screen | full environment: theme, mode, dir, lang, device, scenario, data, i18n, review |
|
|
122
|
+
| `sb:update` | shell → screen | live env change (theme/mode/dir/lang) — no reload |
|
|
123
|
+
| `sb:review` | shell → screen | review state + pins to render |
|
|
124
|
+
| `sb:ready` | screen → shell | `Engine.ready` callbacks ran; hide the veil |
|
|
125
|
+
| `sb:go` | screen → shell | `data-go`/`Engine.go` navigation request |
|
|
126
|
+
| `sb:console-error` | screen → shell | forwarded error (also feeds the self-test) |
|
|
127
|
+
| `sb:pin-request` / `sb:pin-open` | screen → shell | review-mode clicks |
|
|
128
|
+
| `sba:hello` / `sba:screens` / `sba:current` | app → shell | registration, screen list, navigation echo |
|
|
129
|
+
| `sba:go` / `sba:env` | shell → app | drive navigation / apply environment live |
|
|
130
|
+
|
|
131
|
+
## Rules that keep it simple
|
|
132
|
+
|
|
133
|
+
1. **No build, ever.** The studio must run from a folder on disk. Adding a bundler is a
|
|
134
|
+
rejected feature, not a missing one.
|
|
135
|
+
2. **The viewer has zero dependencies; the tooling has one.** Anything heavier belongs in
|
|
136
|
+
a consumer project, not here.
|
|
137
|
+
3. **Screens are standalone documents.** Every screen must work opened directly — the
|
|
138
|
+
bridge's standalone mode is a contract, not a fallback.
|
|
139
|
+
4. **Derived files are never hand-edited** (`manifest.json`), and **every write is
|
|
140
|
+
atomic** (`fsx.js`) — agents and humans share the same safety rails.
|
|
141
|
+
5. **One core, two faces.** New authoring capability goes into `core/project.js` first;
|
|
142
|
+
the CLI command and the MCP tool are wrappers.
|
|
143
|
+
|
|
144
|
+
## Adding things
|
|
145
|
+
|
|
146
|
+
- **A CLI command** → implement against `core/project.js`, register it in the `commands`
|
|
147
|
+
map in `cli/screenbook.js`, document it in [the CLI reference](../reference/cli.md).
|
|
148
|
+
- **An MCP tool** → same core call, plus an entry in `TOOLS` in `mcp/server.js` (schema +
|
|
149
|
+
description are the agent's documentation — write them like you'd brief a new hire).
|
|
150
|
+
- **A studio control** → a widget in `main.js#buildControls()`, state in `store.js`, and a
|
|
151
|
+
reaction in `onChange`; if it must survive reload, add its key to the hash sync.
|
|
152
|
+
- **Anything** → update [the testing map](testing.md) and keep `npm test` +
|
|
153
|
+
`validate` green on the examples.
|
|
@@ -2,21 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
> The "don't forget" file: every test layer, what it covers, how to run it, and where the
|
|
4
4
|
> gaps are. Update this whenever a layer is added or a gap closes. Definition of done for
|
|
5
|
-
> any engine change: **`npm test` green AND `validate` green on
|
|
5
|
+
> any engine change: **`npm test` green AND `validate` green on the bundled examples.**
|
|
6
6
|
|
|
7
7
|
## How to run everything
|
|
8
8
|
|
|
9
|
+
From a checkout of this repo:
|
|
10
|
+
|
|
9
11
|
```bash
|
|
10
|
-
cd engine
|
|
11
12
|
npm i # once — playwright-core (drives your installed Chrome)
|
|
12
|
-
npm test # unit + E2E suites (node:test,
|
|
13
|
+
npm test # unit + E2E suites (node:test, 64 tests, ~60s incl. browser)
|
|
13
14
|
|
|
14
|
-
# full browser matrix on
|
|
15
|
-
node cli/screenbook.js validate .. # Rahhal (repo root)
|
|
15
|
+
# full browser matrix on the projects that ship in this repo:
|
|
16
16
|
node cli/screenbook.js validate examples/qahwa
|
|
17
17
|
node cli/screenbook.js validate examples/tokens-lab
|
|
18
|
+
node cli/screenbook.js validate examples/spa-demo
|
|
18
19
|
```
|
|
19
20
|
|
|
21
|
+
Docs screenshots (`docs/shots/`, light + dark variants of every subject) are regenerated in
|
|
22
|
+
one shot with `node tools/capture-shots.mjs` — it serves scratch copies of the examples, so
|
|
23
|
+
nothing in the repo is mutated by the capture run.
|
|
24
|
+
|
|
20
25
|
## Layers
|
|
21
26
|
|
|
22
27
|
| Layer | File(s) | Covers |
|
|
@@ -36,7 +41,7 @@ node cli/screenbook.js validate examples/tokens-lab
|
|
|
36
41
|
|
|
37
42
|
| Project | Exercises |
|
|
38
43
|
|---------|-----------|
|
|
39
|
-
|
|
|
44
|
+
| the maintainer's host project (not shipped) | iOS frame, AR/RTL/i18n screens, scenarios with `remove`, flows, `statusBar` override, shared.css/js — plus two certified, sealed prototypes embedded as **driven** apps (31 + 11 screens, drivers injected, app files byte-untouched) |
|
|
40
45
|
| `examples/qahwa` | iOS + **Android** + **web** frames in one project, in-screen sheet (EN-24), `Engine.state` cart, feature groups, device filter |
|
|
41
46
|
| `examples/tokens-lab` | **Multi-theme** (Theme ▾ + theme axis in the matrix), **bare `none` frame**, live token re-skin, MutationObserver pattern |
|
|
42
47
|
| `examples/spa-demo` | **Cooperative app mode** — a one-page notes app including `app-bridge.js` itself; engine chrome on an app |
|
|
@@ -50,5 +55,5 @@ node cli/screenbook.js validate examples/tokens-lab
|
|
|
50
55
|
- RTL screenshot diffing / visual regression (screenshots exist; no baseline comparison).
|
|
51
56
|
- Windows: paths are POSIX-tested only; `fs.watch` recursive + rename semantics unverified.
|
|
52
57
|
- `file://` standalone mode has no automated check (manual only; fallback tokens by design).
|
|
53
|
-
- Driven-app injection path in the shell suite uses the cooperative mini-app only;
|
|
54
|
-
|
|
58
|
+
- Driven-app injection path in the shell suite uses the cooperative mini-app only; real
|
|
59
|
+
driven-app drivers are exercised in the maintainer's host project, not by `npm test`.
|
|
@@ -5,20 +5,26 @@ App mode puts the WHOLE app inside the studio: its views appear in the sidebar,
|
|
|
5
5
|
work, dark/RTL/scenario controls drive it — and for sealed apps, **not one byte of the
|
|
6
6
|
app's files changes**.
|
|
7
7
|
|
|
8
|
-

|
|
8
|
+

|
|
9
9
|
|
|
10
10
|
## Register it
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
|
|
13
|
+
screenbook app add legacy/index.html --device ios --chrome self
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
That writes an app-type feature:
|
|
17
17
|
|
|
18
|
-
```
|
|
19
|
-
{
|
|
20
|
-
"
|
|
21
|
-
"
|
|
18
|
+
```jsonc
|
|
19
|
+
{
|
|
20
|
+
"id": "legacy", // feature id — the folder name under features/
|
|
21
|
+
"title": "Legacy app", // shown in the Feature ▾ dropdown
|
|
22
|
+
"type": "app", // app-type feature: one embedded SPA instead of file screens
|
|
23
|
+
"src": "legacy/index.html", // project-relative entry point the studio mounts
|
|
24
|
+
"device": "ios", // bezel: ios · android · web · none
|
|
25
|
+
"chrome": "self", // the app draws its own status/home bars — bezel only
|
|
26
|
+
"driver": "driver.js" // injected adapter (omitted for --cooperative apps)
|
|
27
|
+
}
|
|
22
28
|
```
|
|
23
29
|
|
|
24
30
|
- `device` picks the bezel; `chrome: "self"` means the app draws its own status/home bars
|
|
@@ -72,8 +78,9 @@ reported screen, and **a clean visit to every reported screen — zero console e
|
|
|
72
78
|
Driver bugs surface as `driver <fn>: <message>` rows. `ignoreErrors` patterns are for
|
|
73
79
|
narrow, documented third-party noise only — everything else still fails.
|
|
74
80
|
|
|
75
|
-
## Reference
|
|
81
|
+
## Reference material
|
|
76
82
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
`
|
|
83
|
+
For the **driven** path, `app add` scaffolds a fully commented `driver.js` template — its
|
|
84
|
+
TODOs walk you through `screens()`, `go()` and `set()` against your app's real globals.
|
|
85
|
+
For the **cooperative** path, `examples/spa-demo` inside the package is a complete working
|
|
86
|
+
app to copy from.
|
|
@@ -30,10 +30,16 @@ features/trip-planning/
|
|
|
30
30
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
31
31
|
<title>Home</title>
|
|
32
32
|
<script type="application/json" id="screen-meta">
|
|
33
|
-
{
|
|
34
|
-
"
|
|
33
|
+
{
|
|
34
|
+
"title": "Home",
|
|
35
|
+
"description": "Entry point.",
|
|
36
|
+
"order": 10,
|
|
37
|
+
"device": "ios",
|
|
38
|
+
"status": "wip",
|
|
39
|
+
"tags": ["core"]
|
|
40
|
+
}
|
|
35
41
|
</script>
|
|
36
|
-
<script src="../../../
|
|
42
|
+
<script src="../../../screenbook/bridge.js"></script>
|
|
37
43
|
<link rel="stylesheet" href="shared.css">
|
|
38
44
|
</head>
|
|
39
45
|
<body>
|
|
@@ -80,11 +86,19 @@ Rules that keep everything sane:
|
|
|
80
86
|
|
|
81
87
|
`seed.json` is the demo-complete state. `scenarios.json` layers named states over it:
|
|
82
88
|
|
|
83
|
-
```
|
|
84
|
-
{
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
```jsonc
|
|
90
|
+
{
|
|
91
|
+
"list": [
|
|
92
|
+
{ "id": "default", "icon": "🧪", "title": "Full demo" }, // baseline — the seed, untouched
|
|
93
|
+
{
|
|
94
|
+
"id": "new-user",
|
|
95
|
+
"icon": "🆕",
|
|
96
|
+
"title": "Brand-new user",
|
|
97
|
+
"remove": ["trips", "user.points"], // 1. delete these dot-paths from the seed…
|
|
98
|
+
"patch": { "user": { "isNew": true } } // 2. …then deep-merge this over what's left
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
88
102
|
```
|
|
89
103
|
|
|
90
104
|
`remove` deletes dot-paths, then `patch` deep-merges (arrays replace whole). Date tokens —
|
|
@@ -101,9 +115,11 @@ delta over light. Edit visually in the 🎨 Theme Lab and Save. Register extra t
|
|
|
101
115
|
|
|
102
116
|
`i18n.json`, key-first — every key shows all its languages side by side:
|
|
103
117
|
|
|
104
|
-
```
|
|
105
|
-
{
|
|
106
|
-
"home.
|
|
118
|
+
```jsonc
|
|
119
|
+
{
|
|
120
|
+
"home.title": { "en": "Trips", "ar": "الرحلات" },
|
|
121
|
+
"home.greet": { "en": "{name}, welcome back", "ar": "يا {name}، أهلاً بعودتك" } // {name} fills from Engine.t vars
|
|
122
|
+
}
|
|
107
123
|
```
|
|
108
124
|
|
|
109
125
|
`Engine.t('home.greet', {name})` — fallback: active language → `defaultLanguage` → the key.
|
|
@@ -111,10 +127,20 @@ Language switches reload the screen. Gaps show up as `validate` warnings, never
|
|
|
111
127
|
|
|
112
128
|
## Flows
|
|
113
129
|
|
|
114
|
-
```
|
|
115
|
-
{
|
|
116
|
-
"
|
|
117
|
-
|
|
130
|
+
```jsonc
|
|
131
|
+
{
|
|
132
|
+
"list": [
|
|
133
|
+
{
|
|
134
|
+
"id": "pitch",
|
|
135
|
+
"title": "The pitch",
|
|
136
|
+
"icon": "✨",
|
|
137
|
+
"steps": [
|
|
138
|
+
{ "screen": "010-home", "note": "Start empty.", "scenario": "new-user" }, // a step may pin a scenario
|
|
139
|
+
{ "screen": "020-detail", "note": "One tap deeper." } // …the note is presenter narration
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
}
|
|
118
144
|
```
|
|
119
145
|
|
|
120
146
|
Write notes as presenter narration; 3–7 steps; end on the money shot.
|
|
@@ -122,8 +148,8 @@ Write notes as presenter narration; 3–7 steps; end on the money shot.
|
|
|
122
148
|
## After editing by hand
|
|
123
149
|
|
|
124
150
|
```bash
|
|
125
|
-
|
|
126
|
-
|
|
151
|
+
screenbook manifest # if you added/renamed screens
|
|
152
|
+
screenbook validate # the done gate
|
|
127
153
|
```
|
|
128
154
|
|
|
129
155
|
(Under `serve`, manifests regenerate automatically on save. MCP writes do both for you.)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Getting started
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
| You need | For | Notes |
|
|
6
|
+
|----------|-----|-------|
|
|
7
|
+
| **Node.js ≥ 18** | the CLI, the dev server, the MCP server | the only hard requirement — check with `node --version` |
|
|
8
|
+
| **A modern browser** | the studio itself | Chrome, Safari, Edge, Firefox — the viewer is plain ES modules, no build |
|
|
9
|
+
| **Google Chrome installed** | `validate` and `screenshot` (headless checks) | used through `playwright-core`; see below if you don't have Chrome |
|
|
10
|
+
| **Git** | recommended | ScreenBook writes plain files — git is your undo and your review tool |
|
|
11
|
+
|
|
12
|
+
Nothing else. No bundler, no framework, no build step. The studio itself has **zero**
|
|
13
|
+
dependencies; the CLI carries exactly one (`playwright-core`), used only for headless
|
|
14
|
+
validation and screenshots — it comes along automatically with the install below. On a
|
|
15
|
+
machine without Chrome, the first `validate` downloads a headless browser once, by itself.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
One command, once, globally:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g @cs4alhaider/screenbook
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
That's the entire install — no cloning, nothing copied into your projects. (Prefer no global
|
|
26
|
+
installs? `npx -y @cs4alhaider/screenbook <cmd>` works everywhere `screenbook` appears below.)
|
|
27
|
+
|
|
28
|
+
## Your first project — five minutes
|
|
29
|
+
|
|
30
|
+
Go to **any project you're working on** — an iOS app, a web app, an empty folder — and:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
screenbook init --name "My product"
|
|
34
|
+
screenbook serve
|
|
35
|
+
# → open http://127.0.0.1:4600
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`init` creates one folder, **`.screenbook/`** — the self-contained source of truth for your
|
|
39
|
+
prototype. Commit it or add it to `.gitignore`; your call.
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
.screenbook/
|
|
43
|
+
brief.md ← WRITE YOUR REQUIREMENTS HERE — agents read this first
|
|
44
|
+
app.config.json project name · feature order · devices · themes · languages
|
|
45
|
+
CLAUDE.md the authoring contract (for you AND your AI agents)
|
|
46
|
+
themes/default.json design tokens (light + dark) — edit live in the 🎨 Theme Lab
|
|
47
|
+
features/welcome/ one starter feature with one screen
|
|
48
|
+
feature.json · flows.json · data/seed.json · data/scenarios.json
|
|
49
|
+
screens/010-hello.html ← copy this file to make your second screen
|
|
50
|
+
review/comments.json review pins land here
|
|
51
|
+
.claude/skills/screenbook/ packaged skill so Claude knows the rules instantly
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The studio runtime always comes from the installed package — `screenbook serve` mounts it at
|
|
55
|
+
`/screenbook/` automatically, and screens reference it as `../../../screenbook/bridge.js`.
|
|
56
|
+
|
|
57
|
+
Edit `features/welcome/screens/010-hello.html`, save — the browser reloads itself.
|
|
58
|
+
Copy it to `020-something.html`, change the meta block's `title`/`order`, save — it's in
|
|
59
|
+
the sidebar. That's the whole loop.
|
|
60
|
+
|
|
61
|
+
Already have a single-page prototype? Embed it whole instead of rewriting:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
screenbook init . --app path/to/index.html
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
(see [App mode](app-mode.md)).
|
|
68
|
+
|
|
69
|
+
## The definition of done
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
screenbook validate
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Green means: every screen renders in every theme × light/dark × LTR/RTL with **zero console
|
|
76
|
+
errors**, all metadata is present, every navigation target exists. Make it your habit —
|
|
77
|
+
it's the same gate AI agents are held to.
|
|
78
|
+
|
|
79
|
+
## Offline & prerequisites for the checks
|
|
80
|
+
|
|
81
|
+
Everything runs on your machine — after the one npm install, ScreenBook needs no network at
|
|
82
|
+
all. The automated checks (`screenbook validate`, `screenshot`) drive your installed Google
|
|
83
|
+
Chrome; on a machine without Chrome they download a headless browser once (~120MB),
|
|
84
|
+
automatically. Nobody is ever asked to install anything by hand.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# The studio, control by control
|
|
2
2
|
|
|
3
|
-
Open `http://127.0.0.1:4600`
|
|
3
|
+
Open `http://127.0.0.1:4600` — `screenbook serve` redirects straight to the studio at
|
|
4
|
+
`/screenbook/`.
|
|
4
5
|
|
|
5
|
-

|
|
6
|
+

|
|
6
7
|
|
|
7
8
|
## Top bar
|
|
8
9
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Troubleshooting
|
|
2
2
|
|
|
3
3
|
**The studio is blank / "could not load this project".**
|
|
4
|
-
The
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
The studio expects `app.config.json` one level above where it's mounted. `screenbook serve`
|
|
5
|
+
wires this automatically (the studio lives at `/screenbook/`, your project at `/`). Under a
|
|
6
|
+
plain static server, serve the PROJECT root — never the studio folder itself.
|
|
7
7
|
|
|
8
8
|
**My new screen isn't in the sidebar.**
|
|
9
9
|
The sidebar reads the derived `features/<f>/manifest.json`. Under `serve` it regenerates on
|
|
10
|
-
save; under any other server run `
|
|
10
|
+
save; under any other server run `screenbook manifest`. Also check the
|
|
11
11
|
meta block parses (validate says exactly what's wrong).
|
|
12
12
|
|
|
13
13
|
**The screen shows "Loading…" forever.**
|
|
@@ -23,8 +23,10 @@ the console). Cooperative app: the include path to `engine/app-bridge.js` is wro
|
|
|
23
23
|
them cooperative.
|
|
24
24
|
|
|
25
25
|
**`validate` fails with "No headless browser available".**
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
The checks drive your installed Google Chrome via `playwright-core` (bundled with the
|
|
27
|
+
package), and on a Chrome-less machine they download a headless browser once, automatically.
|
|
28
|
+
If both routes failed (offline machine, blocked download), run
|
|
29
|
+
`npx playwright-core install chromium` when you're back online.
|
|
28
30
|
|
|
29
31
|
**`validate` is red on a screen that looks fine.**
|
|
30
32
|
The gate is zero console errors across every theme × mode × direction. The failure row
|
|
@@ -51,5 +53,6 @@ Python's server sends cache headers; hard-reload, or use `screenbook serve`
|
|
|
51
53
|
(no-store on everything — this problem is why).
|
|
52
54
|
|
|
53
55
|
**Something engine-side looks wrong.**
|
|
54
|
-
`?selftest=1` in the browser for the live matrix;
|
|
55
|
-
(`npm test`
|
|
56
|
+
`?selftest=1` in the browser for the live matrix; the [testing map](../contributing/testing.md)
|
|
57
|
+
covers every layer (`npm test` in a checkout of the ScreenBook repo runs the engine's own
|
|
58
|
+
64-test suite).
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
# CLI reference
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Get the direct `screenbook` command with one global install:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install -g @cs4alhaider/screenbook
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Alternatives that need no install: `npx -y @cs4alhaider/screenbook <command>`, or from a
|
|
10
|
+
checkout `node cli/screenbook.js <command>`. Every command takes an optional project
|
|
11
|
+
directory (default: the current one; running from inside `.screenbook/` resolves to its
|
|
12
|
+
parent project automatically).
|
|
6
13
|
|
|
7
14
|
## `init [dir] [--name X] [--force] [--app <src>] [--cooperative]`
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
screen, `review/`, the agent authoring contract (`CLAUDE.md`) and the packaged skill
|
|
11
|
-
(`.claude/skills/screenbook/`). Refuses to overwrite an existing project without `--force`.
|
|
16
|
+
Create `.screenbook/` in the target project — brief.md (your requirements), app.config.json, starter theme, a `welcome` feature, review/, the agent authoring contract, plus the packaged skill at `.claude/skills/screenbook/`. The folder is the prototype's source of truth; commit or gitignore it. Refuses to overwrite an existing `.screenbook/` without `--force`.
|
|
12
17
|
`--app path/to/index.html` additionally registers an existing SPA in that folder as an
|
|
13
18
|
embedded app (driver scaffolded unless `--cooperative`).
|
|
14
19
|
|
|
@@ -16,8 +21,8 @@ embedded app (driver scaffolded unless `--cooperative`).
|
|
|
16
21
|
|
|
17
22
|
The dev server. Static hosting with:
|
|
18
23
|
|
|
19
|
-
-
|
|
20
|
-
|
|
24
|
+
- the studio runtime mounted at `/screenbook/*` straight from the installed package
|
|
25
|
+
(`/engine/*` kept as a compatibility alias) — your project never carries runtime code
|
|
21
26
|
- live reload over SSE — saving any project file refreshes the studio; screen edits reload
|
|
22
27
|
the current frame
|
|
23
28
|
- automatic `manifest.json` regeneration when screens change
|
|
@@ -53,8 +58,8 @@ Device-framed PNGs via headless Chrome. Options: `--mode light,dark` · `--dir l
|
|
|
53
58
|
|
|
54
59
|
Embed an existing single-page app as an app-type feature. Scaffolds an injectable
|
|
55
60
|
`driver.js` template (fill in `screens()` / `go()` / `set()`) unless `--cooperative`, in
|
|
56
|
-
which case the app is expected to include `
|
|
57
|
-
[App mode](app-mode
|
|
61
|
+
which case the app is expected to include the packaged `app-bridge.js` itself. See
|
|
62
|
+
[App mode](../guides/app-mode.md).
|
|
58
63
|
|
|
59
64
|
## `mcp [--root dir]`
|
|
60
65
|
|
|
@@ -15,11 +15,11 @@ claude mcp add screenbook -- npx -y @cs4alhaider/screenbook mcp --root .
|
|
|
15
15
|
Working from a checkout instead (engine copied into the project)? Point at it directly:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
|
|
18
|
+
node <path-to-package>/cli/screenbook.js mcp --root . # rarely needed
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
`--root` points at
|
|
22
|
-
dropped `
|
|
21
|
+
`--root` points at your project directory — the `.screenbook/` inside it is found automatically. `init` has already
|
|
22
|
+
dropped `AGENTS.md` (the universal contract) and the `screenbook` skill into the project, so a fresh Claude session
|
|
23
23
|
knows the rules the moment it opens the folder.
|
|
24
24
|
|
|
25
25
|
## What agents can do
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"updated": "2026-07-18"
|
|
17
17
|
}
|
|
18
18
|
</script>
|
|
19
|
-
<script src="../../../
|
|
19
|
+
<script src="../../../screenbook/bridge.js"></script>
|
|
20
20
|
<link rel="stylesheet" href="shared.css">
|
|
21
21
|
<style>
|
|
22
22
|
.stepper { position: relative; padding-inline-start: 26px; }
|