@madojs/mado 0.5.0 → 0.6.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 (122) hide show
  1. package/AGENTS.md +49 -1
  2. package/CHANGELOG.md +188 -0
  3. package/MADO_V1_PLAN.md +179 -0
  4. package/README.md +53 -14
  5. package/ROADMAP.md +36 -5
  6. package/TODO.md +72 -0
  7. package/dist/src/forms.d.ts +41 -7
  8. package/dist/src/forms.js +334 -59
  9. package/dist/src/forms.js.map +1 -1
  10. package/dist/src/html/bindings.d.ts +41 -0
  11. package/dist/src/html/bindings.js +163 -6
  12. package/dist/src/html/bindings.js.map +1 -1
  13. package/dist/src/html.d.ts +2 -0
  14. package/dist/src/html.js +1 -0
  15. package/dist/src/html.js.map +1 -1
  16. package/dist/src/index.d.ts +6 -6
  17. package/dist/src/index.js +2 -2
  18. package/dist/src/index.js.map +1 -1
  19. package/dist/src/page.d.ts +56 -0
  20. package/dist/src/page.js +17 -0
  21. package/dist/src/page.js.map +1 -1
  22. package/dist/src/router/manifest.d.ts +16 -1
  23. package/dist/src/router/manifest.js +181 -38
  24. package/dist/src/router/manifest.js.map +1 -1
  25. package/dist/src/router/match.d.ts +7 -2
  26. package/dist/src/router/match.js +14 -4
  27. package/dist/src/router/match.js.map +1 -1
  28. package/dist/src/router/navigation.d.ts +10 -0
  29. package/dist/src/router/navigation.js +73 -12
  30. package/dist/src/router/navigation.js.map +1 -1
  31. package/dist/src/signal.d.ts +15 -1
  32. package/dist/src/signal.js +112 -16
  33. package/dist/src/signal.js.map +1 -1
  34. package/docs/en/02-project-layout.md +99 -40
  35. package/docs/en/05-why-mado.md +1 -1
  36. package/docs/en/06-for-backenders.md +1 -1
  37. package/docs/en/07-llm-pitfalls.md +1 -1
  38. package/docs/en/09-shadow-vs-light-dom.md +60 -0
  39. package/docs/en/10-app-architecture.md +141 -0
  40. package/docs/en/11-layouts.md +115 -0
  41. package/docs/en/12-auth-and-api.md +217 -0
  42. package/docs/en/13-deployment.md +192 -0
  43. package/docs/en/14-testing.md +82 -0
  44. package/docs/en/15-error-handling.md +100 -0
  45. package/docs/en/16-bake-cookbook.md +93 -0
  46. package/docs/en/README.md +7 -0
  47. package/docs/fr/05-why-mado.md +1 -1
  48. package/docs/fr/06-for-backenders.md +1 -1
  49. package/docs/fr/07-llm-pitfalls.md +1 -1
  50. package/docs/fr/09-shadow-vs-light-dom.md +63 -0
  51. package/docs/fr/10-app-architecture.md +61 -0
  52. package/docs/fr/11-layouts.md +35 -0
  53. package/docs/fr/12-auth-and-api.md +35 -0
  54. package/docs/fr/13-deployment.md +39 -0
  55. package/docs/fr/14-testing.md +41 -0
  56. package/docs/fr/15-error-handling.md +50 -0
  57. package/docs/fr/16-bake-cookbook.md +35 -0
  58. package/docs/fr/README.md +7 -0
  59. package/docs/ru/05-why-mado.md +2 -2
  60. package/docs/ru/06-for-backenders.md +1 -1
  61. package/docs/ru/09-shadow-vs-light-dom.md +60 -0
  62. package/docs/ru/10-app-architecture.md +100 -0
  63. package/docs/ru/11-layouts.md +47 -0
  64. package/docs/ru/12-auth-and-api.md +53 -0
  65. package/docs/ru/13-deployment.md +60 -0
  66. package/docs/ru/14-testing.md +50 -0
  67. package/docs/ru/15-error-handling.md +56 -0
  68. package/docs/ru/16-bake-cookbook.md +55 -0
  69. package/docs/ru/README.md +7 -0
  70. package/docs/uk/06-for-backenders.md +2 -2
  71. package/docs/uk/09-shadow-vs-light-dom.md +91 -24
  72. package/docs/uk/10-app-architecture.md +56 -0
  73. package/docs/uk/11-layouts.md +34 -0
  74. package/docs/uk/12-auth-and-api.md +34 -0
  75. package/docs/uk/13-deployment.md +39 -0
  76. package/docs/uk/14-testing.md +34 -0
  77. package/docs/uk/15-error-handling.md +32 -0
  78. package/docs/uk/16-bake-cookbook.md +36 -0
  79. package/docs/uk/README.md +7 -0
  80. package/llms.txt +24 -1
  81. package/package.json +3 -1
  82. package/scripts/_config.mjs +224 -0
  83. package/scripts/bake.mjs +217 -120
  84. package/scripts/bundle.mjs +110 -67
  85. package/scripts/cli.mjs +127 -16
  86. package/scripts/preview.mjs +22 -12
  87. package/server/serve.mjs +101 -11
  88. package/starters/admin/README.md +63 -0
  89. package/starters/admin/index.html +21 -0
  90. package/starters/admin/mado.config.json +22 -0
  91. package/starters/admin/package.json +22 -0
  92. package/starters/admin/public/favicon.svg +4 -0
  93. package/starters/admin/src/components/x-button.ts +55 -0
  94. package/starters/admin/src/components/x-input.ts +74 -0
  95. package/starters/admin/src/layouts/app.ts +101 -0
  96. package/starters/admin/src/layouts/auth.ts +41 -0
  97. package/starters/admin/src/lib/api.ts +133 -0
  98. package/starters/admin/src/lib/auth.ts +83 -0
  99. package/starters/admin/src/main.ts +15 -0
  100. package/starters/admin/src/pages/admin/dashboard.ts +48 -0
  101. package/starters/admin/src/pages/admin/order-detail.ts +78 -0
  102. package/starters/admin/src/pages/admin/orders.ts +117 -0
  103. package/starters/admin/src/pages/home.ts +25 -0
  104. package/starters/admin/src/pages/login.ts +70 -0
  105. package/starters/admin/src/pages/not-found.ts +12 -0
  106. package/starters/admin/src/routes.ts +40 -0
  107. package/starters/admin/src/styles/global.ts +86 -0
  108. package/starters/admin/tsconfig.json +15 -0
  109. package/starters/crud/README.md +14 -2
  110. package/starters/crud/mado.config.json +20 -0
  111. package/starters/crud/package.json +9 -4
  112. package/starters/crud/src/components/app-shell.ts +13 -8
  113. package/starters/crud/src/main.ts +1 -4
  114. package/starters/crud/src/pages/ticket-detail.ts +1 -0
  115. package/starters/crud/src/pages/ticket-new.ts +1 -0
  116. package/starters/crud/src/pages/tickets.ts +1 -0
  117. package/starters/crud/src/routes.ts +4 -2
  118. package/starters/minimal/README.md +4 -2
  119. package/starters/minimal/mado.config.json +20 -0
  120. package/starters/minimal/package.json +8 -3
  121. package/starters/minimal/src/components/app-counter.ts +1 -1
  122. package/starters/minimal/src/routes.ts +4 -2
package/AGENTS.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  > This file is read by AI agents in IDEs (Cursor, Cline, Copilot, Continue, etc.).
4
4
  > Goal: prevent them from generating React-like code where Mado should be used.
5
+ >
6
+ > The v0.6 product-surface push is archived in
7
+ > [`MADO_V1_PLAN.md`](./MADO_V1_PLAN.md). New work should follow `ROADMAP.md`
8
+ > / `TODO.md` unless the user explicitly resumes that tracker.
5
9
 
6
10
  ## Project at a glance
7
11
 
@@ -247,6 +251,28 @@ component("x-child", ({ host }) => {
247
251
  });
248
252
  ```
249
253
 
254
+ ### 13. Component registration imports
255
+
256
+ Custom elements are global after registration, but the browser never imports a
257
+ component file automatically.
258
+
259
+ ```ts
260
+ import "./components/app-shell.js";
261
+
262
+ render(html`<x-app-shell>${router.view}</x-app-shell>`, app);
263
+ ```
264
+
265
+ The import runs `customElements.define("x-app-shell", ...)`. After that,
266
+ `<x-app-shell>` works anywhere in the current document.
267
+
268
+ Rules:
269
+
270
+ - App shell / global providers → import in `main.ts`.
271
+ - Components used only by one page → import in that page.
272
+ - Components shared by a feature → import in the feature entry/page.
273
+ - Tiny leaf components used everywhere → importing in `main.ts` is acceptable.
274
+ - Do **not** bulk-import every component "just in case".
275
+
250
276
  ## SOFT GUIDELINES — recommended, but not critical
251
277
 
252
278
  - **TypeScript strict.** Use `noUncheckedIndexedAccess`-aware code (with `!` or a type guard).
@@ -263,10 +289,29 @@ src/
263
289
  ├── main.ts ← entry: mount to #app
264
290
  ├── pages/ ← one page = one file
265
291
  ├── components/ ← reusable x-* components
266
- ├── layouts/ ← layout for nested routes
292
+ ├── layouts/ ← optional route layout modules (`page({ child })`)
267
293
  └── lib/ ← API client, contexts, pure logic
268
294
  ```
269
295
 
296
+ ## App architecture for LLM
297
+
298
+ When generating an app, prefer the blessed production shape from
299
+ `docs/en/10-app-architecture.md` and the `starters/admin/` example:
300
+
301
+ - `src/main.ts` mounts `routesApi.view` and imports only global styles,
302
+ providers, and tiny shared components.
303
+ - `src/routes.ts` exports both `manifest` and `default routes(manifest, ...)`.
304
+ - Put route wrappers in `src/layouts/` via `layout()`, not ad-hoc shell logic
305
+ inside every page.
306
+ - Put backend access in `src/lib/api.ts` and auth/session logic in
307
+ `src/lib/auth.ts`; guards call auth helpers, pages call API helpers.
308
+ - Put one page per file under `src/pages/`; a page imports the feature
309
+ components it renders.
310
+ - Use `resource()` for reads, `mutation(..., { invalidates })` for writes,
311
+ and `useForm()` for form state/validation.
312
+ - Use `mado release` as the production path. `out/` is the only deploy
313
+ artifact; `dist/` is internal build output.
314
+
270
315
  ## Where to find specific answers
271
316
 
272
317
  | Question | File |
@@ -276,6 +321,9 @@ src/
276
321
  | How does the router work? | `src/router.ts` (~530 lines) |
277
322
  | How does resource + cache work? | `src/resource.ts` (297 lines) |
278
323
  | How do forms work? | `src/forms.ts` (212 lines) |
324
+ | How should an app be structured? | `docs/en/10-app-architecture.md` |
325
+ | How should errors be handled? | `docs/en/15-error-handling.md` |
326
+ | How should bake be used? | `docs/en/16-bake-cookbook.md` |
279
327
  | When something goes wrong | `docs/en/07-llm-pitfalls.md` |
280
328
 
281
329
  ## Before committing
package/CHANGELOG.md CHANGED
@@ -1,5 +1,193 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ Nothing yet.
6
+
7
+ ## 0.6.0
8
+
9
+ Product-surface release: app-mode defaults, blessed admin starter, release
10
+ pipeline, core hardening and v1 recipe docs.
11
+
12
+ Phase 1 — Repo-vs-app split:
13
+
14
+ ### Added
15
+ - `MADO_V1_PLAN.md` — executable tracker for the v1 push.
16
+ - `scripts/_config.mjs` — single configuration loader (defaults < `mado.config.json`
17
+ < CLI flags). Exports `loadConfig`, `detectContext`, `parseFlags`,
18
+ `resolveProjectPath`. [v1 F1.1]
19
+ - `mado release` command: one-shot `typecheck + build + bundle + bake + copy
20
+ public/ → out/` pipeline so apps have exactly one command to ship. [v1 F1.3]
21
+ - `mado.config.json` shipped in the `minimal` and `crud` starters with the
22
+ default app-mode layout (`src/routes.ts`, `index.html`, `out/`). [v1 F1.4]
23
+ - Tests: `test/config-loader.test.mjs`, `test/bake-cli.test.mjs` (11 + 3
24
+ cases covering context detection, config precedence, flag parsing, bake
25
+ flags, and the no-more-silent-`[object Object]` contract). [v1 F1.6]
26
+
27
+ ### Changed
28
+ - `scripts/bake.mjs` now reads configuration from `mado.config.json` and
29
+ accepts `--entry`, `--template`, `--out`, `--base-url` flags. In app-mode
30
+ defaults are `src/routes.ts` + `index.html` + `out/baked/`; the
31
+ `@madojs/mado → src/index.ts` alias is repo-only. [v1 F1.2]
32
+ - `scripts/bake.mjs` no longer renders unsupported values as `[object Object]`;
33
+ it raises a loud, file/route-targeted error with a hint instead. [v1 F1.2]
34
+ - `scripts/cli.mjs` detects repo-vs-app context, advertises `mado release`,
35
+ and ships a redesigned `mado help` that explains the dev / build / release
36
+ / preview pipeline. [v1 F1.3]
37
+ - Starter `package.json` scripts go through the `mado` CLI exclusively
38
+ (`mado build`, `mado dev`, `mado bundle`, `mado bake`, `mado release`,
39
+ `mado preview`). [v1 F1.4]
40
+ - `docs/en/02-project-layout.md` rewritten around the canonical `src/` /
41
+ `dist/` / `public/` / `out/` model plus a `mado.config.json` one-screen
42
+ reference. [v1 F1.5]
43
+ - `ROADMAP.md`, `TODO.md`, `AGENTS.md` now distinguish the completed
44
+ `MADO_V1_PLAN.md` archive from future roadmap/TODO work. [v1 F0]
45
+
46
+ Phase 2 — One blessed way:
47
+
48
+ ### Added
49
+ - `layout()` factory in `src/page.ts` (alias of `nested()`) plus `Guard` and
50
+ `GuardResult` types. Exported from the public API. [v1 F2.1 / F2.3]
51
+ - Route guards: nested groups and individual pages accept `guard: Guard | Guard[]`.
52
+ Verdicts: void (pass), `{ halt: true }`, or `{ redirect, replace? }`. Async-aware
53
+ with a sync fast path; throwing guards are treated as `halt`. [v1 F2.2]
54
+ - New starter `starters/admin/`: nested manifest with `/`, `/login`, `/admin`
55
+ groups; blessed `lib/api.ts` (`createApiClient`, `ApiError`, single-flight
56
+ 401-refresh) and `lib/auth.ts` (`accessToken`, `restoreSession`, `requireAuth`,
57
+ `login`, `logout`); `layouts/{app,auth}.ts` with a real admin shell; tiny
58
+ `x-button`/`x-input` design-token components; dashboard + orders + order-detail
59
+ pages; `mado.config.json` with a dev `/api` proxy; `public/favicon.svg`. [v1 F2.4]
60
+ - CLI advertises `mado init <name> --starter admin` and lists it in `mado help`.
61
+ [v1 F2.5]
62
+ - `docs/en/11-layouts.md` — the canonical layout recipe (nested routes) plus
63
+ two acceptable alternatives with caveats. [v1 F2.6]
64
+ - `docs/en/12-auth-and-api.md` — the blessed `api`/`auth` recipes, backend
65
+ contract, and dev-proxy hint. [v1 F2.7]
66
+ - `test/guards-layouts.test.mjs` — 7 cases covering the public `layout()`
67
+ alias, sync pass/halt/redirect, async guards, parent→page guard order, and
68
+ throwing-guard fallback. [v1 F2.8]
69
+
70
+ Phase 3 — Bake first-class + Release pipeline:
71
+
72
+ ### Added
73
+ - `mado release` writes `_redirects` (`/* /index.html 200`) and `_headers`
74
+ (immutable for `/assets/*`, no-cache for HTML) into `out/` when they do not
75
+ exist, so Cloudflare Pages / Netlify deploys "just work". [v1 F3.7]
76
+ - `docs/en/13-deployment.md` — VPS + nginx, Cloudflare Pages, S3/CloudFront,
77
+ Netlify and GitHub Pages recipes; cache-control matrix; GitHub Actions
78
+ release sketch; troubleshooting (deep-link 404, HTML caching, `[object Object]`).
79
+ [v1 F3.8 / F3.9]
80
+ - `test/release-pipeline.test.mjs` — end-to-end test: scaffold a temp app,
81
+ symlink the local framework, run `mado release`, assert that `out/index.html`,
82
+ `out/baked/index.html`, `out/baked/sitemap.xml`, `out/_redirects`, `out/_headers`,
83
+ and copied `public/` assets are all present. [v1 F3.10]
84
+
85
+ ### Changed
86
+ - `scripts/preview.mjs` now reads `mado.config.json` (`build.out`, `dev.port`),
87
+ refuses to auto-build by default in app-mode, and asks the user to run
88
+ `mado release` first. Legacy auto-build is opt-in via `PREVIEW_AUTOBUILD=1`
89
+ for the framework repo. [v1 F3.3]
90
+ - `scripts/bundle.mjs` is now app-mode aware: reads `mado.config.json` for
91
+ defaults, accepts `--entry/--html/--out` flags, and writes hashed bundles
92
+ into `out/assets/` so the new nginx / Cloudflare cache rules apply. The old
93
+ `examples/showcase` defaults are kept only in repo-mode for dogfooding.
94
+ [v1 F3.10]
95
+ - `server/serve.mjs` honors `dev.proxy` from `mado.config.json` and forwards
96
+ matching prefixes (e.g. `/api → http://localhost:3000`) without external
97
+ dependencies. The startup banner prints the active proxy table. [v1 F3.6]
98
+
99
+ ### Deferred to v0.7
100
+ - `mado dev` does not yet serve baked routes inline. Workaround: run
101
+ `mado release && mado preview`. [v1 F3.2]
102
+ - `mado check` (bake-safety scan over `bake:` routes) is not exposed yet.
103
+ The loud-error contract in `scripts/bake.mjs` covers the regression case.
104
+ [v1 F3.5]
105
+
106
+ Phase 4 — Core hardening:
107
+
108
+ ### Added
109
+ - `computed(fn, { equals })` option to suppress subscriber reruns when an
110
+ observed computed recomputes to an equal value. [v1 F4.3]
111
+ - HTML directives: `unsafeHTML()`, `ref()`, `classMap()` and `styleMap()` are
112
+ exported from the public API. Runtime bindings enforce valid positions and
113
+ clean up stale classes/styles/refs on updates and disposal. Bake can serialize
114
+ the static directive shapes it can safely represent. [v1 F4.4]
115
+ - `useForm()` now supports async validators via form-level `validateAsync`,
116
+ field-level `validateAsync`, `validating` / `validatingFields`, and explicit
117
+ `validate()` / `validateField()` methods. [v1 F4.5]
118
+ - `useForm().array(name)` adds a small field-array helper with dotted path names
119
+ (`items.0.title`) and wildcard schema validation (`items.*.title`). [v1 F4.5]
120
+ - `test/signal-cycle.test.mjs` covers self-triggering effect cycle detection.
121
+ [v1 F4.2]
122
+ - `test/html-directives.test.mjs` covers directive rendering, cleanup and
123
+ invalid child-position usage. [v1 F4.4]
124
+ - `test/forms.test.mjs` covers async validator races, async submit blocking,
125
+ and field-array wildcard validation. [v1 F4.5]
126
+ - Phase 4 now has an explicit coverage audit tying every core-hardening task to
127
+ its regression tests. [v1 F4.9]
128
+
129
+ ### Changed
130
+ - `computed()` now releases dependency subscriptions after unobserved reads and
131
+ after the last subscriber is disposed, avoiding long-lived stale subscriptions
132
+ in the signal graph. [v1 F4.1]
133
+ - The effect scheduler now detects runaway self-triggering cycles and emits a
134
+ clear diagnostic instead of flushing forever. [v1 F4.2]
135
+ - Runtime head management now clears Mado-managed tags on every navigation,
136
+ including pages without `head()` and pages whose `head()` throws, so stale
137
+ baked/runtime SEO tags cannot leak across routes. [v1 F4.8]
138
+ - Router navigation now saves/restores scroll positions for back/forward,
139
+ scrolls new navigations to the top, and moves focus to the main content
140
+ landmark after navigation. [v1 F4.6]
141
+ - `routes()` now supports a global `errorPage(err, params)` route boundary for
142
+ lazy loader, `load()` and `view()` errors, while local `page.errorView` still
143
+ wins. [v1 F4.7]
144
+
145
+ Phase 5 — Documentation:
146
+
147
+ ### Added
148
+ - `docs/en/10-app-architecture.md`, `14-testing.md`, `15-error-handling.md`
149
+ and `16-bake-cookbook.md` complete the v1 English recipe set. [v1 F5.1-F5.4]
150
+ - `AGENTS.md` now includes an "App architecture for LLM" section and `llms.txt`
151
+ links the v1 architecture, layout, auth/API, deployment, testing,
152
+ error-handling and bake docs. [v1 F5.5-F5.6]
153
+ - Russian, French and Ukrainian documentation now includes localized versions of
154
+ the v1 recipe docs `10` through `16`. [v1 F5.7]
155
+
156
+ ## 0.5.1
157
+
158
+ Patch release focused on first-user DX after the public npm launch.
159
+
160
+ ### Fixed
161
+
162
+ - Generated starter apps can now run `mado dev` / `mado serve` from the app
163
+ root instead of assuming the framework repository layout.
164
+ - The CRUD starter shell is a real Web Component again, using Shadow DOM and
165
+ `<slot>` for route projection.
166
+ - Feature components in the CRUD starter are imported by the pages that render
167
+ them, avoiding a confusing "import everything in main" pattern.
168
+ - The minimal starter counter tag registration now matches the rendered
169
+ `<x-app-counter>` tag.
170
+ - The router default 404 view is rendered through `html` templates, not dynamic
171
+ `innerHTML`.
172
+ - `npm run bundle` defaults to the existing showcase entry instead of the old
173
+ removed `examples/main.ts`.
174
+
175
+ ### Changed
176
+
177
+ - Starter packages include `npm run dev` and generated `.gitignore` defaults.
178
+ - README and docs clarify that Mado works with browser primitives rather than
179
+ replacing the platform.
180
+ - Form documentation now describes `useForm()` as schema-based validation close
181
+ to HTML constraints, matching the implementation.
182
+ - Shadow DOM / Light DOM docs now explain layout components, `<slot>`, and
183
+ component registration imports.
184
+ - Deep imports are documented as internal/unstable before v1.
185
+ - CI workflows use Node24-based GitHub actions and the obsolete Cloudflare
186
+ showcase deploy workflow was removed.
187
+ - The release workflow updates npm before publish and creates GitHub releases
188
+ through the GitHub CLI.
189
+ - Browser regression now runs on a weekly schedule as well as manually.
190
+
3
191
  ## 0.5.0
4
192
 
5
193
  First public release preparation for Mado.
@@ -0,0 +1,179 @@
1
+ # MadoJS — Road to v1 (completed v0.6 tracker)
2
+
3
+ > Completed tracker for the v0.6 product-surface push. The work agreed during
4
+ > the v1 audit is now closed and squash-merged into `main` as
5
+ > `feat: add v1 product surface`.
6
+ >
7
+ > Convention: every commit/PR that advances v1 references task IDs in its message,
8
+ > e.g. `[v1 F1.2] bake.mjs: app-mode defaults + --entry/--template/--out flags`.
9
+ > When a task is completed, tick its box here in the same commit.
10
+
11
+ ---
12
+
13
+ ## 0. Mental model (write this into docs first)
14
+
15
+ Three artifact states. One deploy artifact. End of story.
16
+
17
+ | Folder | What it is | Who writes | Who reads | Deployed? |
18
+ |-------------|----------------------------------------------------------------|-------------------|----------------------------|-------------------|
19
+ | `src/` | your source (TS) | you | `tsc`, `esbuild` | no |
20
+ | `dist/` | `tsc` output (native ESM JS for the browser) | `mado build` | `mado dev`, dev browser | no (internal) |
21
+ | `public/` | static assets (favicons, images, robots.txt) | you | `mado bundle` copies it | as part of `out/` |
22
+ | `out/` | **the only deploy artifact**: SPA shell + bundles + baked HTML | `mado release` | nginx / CDN / CF / VPS | ✅ yes |
23
+
24
+ One-liner for users:
25
+ > Develop with `mado dev`. To deploy: run `mado release`, then upload `out/` anywhere.
26
+
27
+ `mado release` = `typecheck` + `build` + `bundle` + `bake` + copy `public/*` → `out/`.
28
+ One command. One artifact. Zero questions about where things live.
29
+
30
+ ---
31
+
32
+ ## 1. Problem map (consolidated)
33
+
34
+ ### Layer A — Core (from the audit)
35
+ - **A1** Computed leaks: no refcount/owner; once read, computed stays subscribed to deps forever.
36
+ - **A2** No cycle-detection in `effect` (e.g. `effect(() => x.set(x()+1))` runs forever).
37
+ - **A3** No `equals` option on `computed`.
38
+ - **A4** No template directives: `unsafeHTML`, `ref`, `classMap`, `styleMap`.
39
+ - **A5** `useForm`: no async validators, no field-arrays.
40
+ - **A6** `resource`/`invalidate`: no typed key relationship; pattern miss is silent.
41
+ - **A7** Router: no scroll restoration / focus management / error boundary.
42
+ - **A8** `head()`: not obvious how dedup/cleanup happens across navigation.
43
+
44
+ ### Layer B — DX, tooling, product surface (from dogfooding)
45
+ - **B1** CLI/bake hardcoded to `examples/` and alias `@madojs/mado → src/index.ts` — repo-mode leaks into user apps.
46
+ - **B2** No single blessed way for **layouts** (LLM and humans both guess).
47
+ - **B3** No blessed way for **auth + API client + dev-proxy**.
48
+ - **B4** No single config file (`mado.config.json`); everything is env vars.
49
+ - **B5** Unclear model for `dist/` vs `out/` vs `public/`.
50
+ - **B6** No `mado release` (one deploy artifact).
51
+ - **B7** Bake silently renders `[object Object]` for `each()`.
52
+ - **B8** Bake lives "next to" the app instead of inside `mado dev`.
53
+ - **B9** No route guard API.
54
+ - **B10** `crud` starter looks like raw scaffold; no admin-template.
55
+ - **B11** Docs missing: app-architecture, layouts, auth-and-api, deployment, testing, error-handling, bake-cookbook.
56
+ - **B12** Starter scaffolds contain `examples/` legacy.
57
+
58
+ ---
59
+
60
+ ## 2. Phases (deliver in order; phase 5 runs in parallel)
61
+
62
+ ### 🟦 Phase 1 — Repo-vs-app split (P0)
63
+
64
+ Goal: kill `examples/` leakage; make app-mode the default.
65
+
66
+ ### 🟩 Phase 2 — One blessed way (P0)
67
+
68
+ Goal: conventions over flexibility. Layouts, guards, auth, api — one recipe each.
69
+
70
+ ### 🟨 Phase 3 — Bake first-class + Release pipeline (P0)
71
+
72
+ Goal: pragmatic path from `mado dev` to production on VPS / Cloudflare / static CDN.
73
+
74
+ ### 🟪 Phase 4 — Core hardening (P1)
75
+
76
+ Goal: long-term correctness of signals, html, router, forms, head.
77
+
78
+ ### 🟫 Phase 5 — Documentation (P0/P1, in parallel)
79
+
80
+ Goal: a backender can ship an admin app reading only the docs.
81
+
82
+ ---
83
+
84
+ ## 3. Acceptance scenario for v1
85
+
86
+ ```bash
87
+ npm exec --package @madojs/mado@latest -- mado init dashboard --starter admin
88
+ cd dashboard
89
+ npm install
90
+ mado dev
91
+ # / → public landing
92
+ # /admin → redirected to /login (guard works)
93
+ # log in → admin shell with sidebar / topbar / dashboard / orders table
94
+
95
+ mado release
96
+ rsync -avz out/ user@vps:/var/www/dashboard/
97
+ # done
98
+ ```
99
+
100
+ If a backend developer reaches production **without reading `bake.mjs`,
101
+ without setting env vars, without asking "where does layout live?",
102
+ and without an `examples/` folder in their app** — v1 is done.
103
+
104
+ ---
105
+
106
+ ## 4. Tracker
107
+
108
+ ### Phase 1 — Repo-vs-app split ✅
109
+ - [x] **F1.1** `mado.config.json` schema + loader (`scripts/_config.mjs`)
110
+ - [x] **F1.2** `scripts/bake.mjs`: flags `--entry/--template/--out/--base-url`, app-mode defaults, no `examples/` alias in app-mode, loud errors instead of silent `[object Object]`
111
+ - [x] **F1.3** `scripts/cli.mjs`: detect repo vs app, read `mado.config.json`, redesigned help, new `mado release` command
112
+ - [x] **F1.4** Starters cleanup: `mado.config.json` and blessed CLI scripts in `starters/minimal` and `starters/crud`; no `examples/` references
113
+ - [x] **F1.5** `docs/en/02-project-layout.md` rewritten around the canonical `src/`/`dist/`/`public/`/`out/` model and `mado.config.json`
114
+ - [x] **F1.6** `test/config-loader.test.mjs` + `test/bake-cli.test.mjs`.
115
+
116
+ ### Phase 2 — One blessed way ✅
117
+ - [x] **F2.1** `layout()` factory (alias of `nested()`) exported from `src/page.ts`; flatten propagates layouts outer → inner.
118
+ - [x] **F2.2** `Guard` type + guard chain in `src/router/manifest.ts`. Verdicts: void / `{ halt: true }` / `{ redirect, replace? }`. Async-aware with sync fast path; throwing guard is treated as `halt` with a `console.error`.
119
+ - [x] **F2.3** `layout`, `Guard`, `GuardResult`, `nested`, `navigate` exported from `src/index.ts`.
120
+ - [x] **F2.4** New starter `starters/admin/` with `layouts/{app,auth}.ts`, `lib/{api,auth}.ts`, `components/{x-button,x-input}.ts`, `pages/{home,login,not-found,admin/{dashboard,orders,order-detail}}.ts`, `styles/global.ts`, `mado.config.json`, `public/favicon.svg`. End-to-end scaffold + typecheck + build verified locally.
121
+ - [x] **F2.5** CLI advertises `--starter admin` (`mado init my-app --starter admin`) and adds it to the help screen.
122
+ - [x] **F2.6** Doc `docs/en/11-layouts.md` (one path + 2 alternatives with caveats).
123
+ - [x] **F2.7** Doc `docs/en/12-auth-and-api.md` (blessed `api`/`auth` recipes, backend contract, dev-proxy hint).
124
+ - [x] **F2.8** `test/guards-layouts.test.mjs` covers the public `layout()` alias, sync pass/halt/redirect verdicts, async guards, parent→page guard order, and throwing-guard fallback (7 tests, all green).
125
+
126
+ ### Phase 3 — Bake first-class + Release pipeline ✅ (core)
127
+ - [x] **F3.1** `mado release` command: typecheck + build + bundle + bake + copy `public/` → `out/` + write `_headers` / `_redirects` (`scripts/cli.mjs`).
128
+ - [x] **F3.2** Deferred to v0.7: `mado dev` serves baked routes inline. Current v1 path is `mado release && mado preview`.
129
+ - [x] **F3.3** `mado preview` reads `mado.config.json`, refuses to auto-build in app-mode (opt in with `PREVIEW_AUTOBUILD=1`), and emulates nginx fallback (`scripts/preview.mjs`).
130
+ - [x] **F3.4** Bake raises a loud, file/route-targeted error on unsupported render values (e.g. `each()` directive objects). Covered by `test/bake-cli.test.mjs`.
131
+ - [x] **F3.5** Deferred to v0.7: `mado check` runs bake-safety scan on `bake:` routes. Current v1 coverage is the loud-error contract from F3.4.
132
+ - [x] **F3.6** Dev-proxy in `server/serve.mjs`: reads `dev.proxy` from `mado.config.json` and forwards matching prefixes to the upstream backend without external deps.
133
+ - [x] **F3.7** `mado release` generates `out/_redirects` (`/* /index.html 200`) and `out/_headers` (immutable for `/assets/*`, no-cache for `/*.html`) when those files do not exist.
134
+ - [x] **F3.8** Doc `docs/en/13-deployment.md` (VPS + nginx, Cloudflare Pages, S3/CloudFront, Netlify, GitHub Pages, CI sketch, cache matrix, troubleshooting).
135
+ - [x] **F3.9** Production `nginx.conf` next to the docs (already shipped, with `gzip_static`, immutable hashed bundles, SPA fallback). Verified referenced from the deployment doc.
136
+ - [x] **F3.10** `test/release-pipeline.test.mjs`: end-to-end CLI test scaffolds an app, runs `mado release`, and asserts `out/index.html`, `out/baked/index.html`, `out/_headers`, `out/_redirects`, public-asset copy, and sitemap. Also `scripts/bundle.mjs` is app-mode aware (no `examples/`-leak when run from a user app).
137
+
138
+ ### Phase 4 — Core hardening
139
+ - [x] **F4.1** Refcount/GC for `computed` in `src/signal.ts` + tests (`computed` releases dep subscriptions after unobserved reads and after the last subscriber is disposed).
140
+ - [x] **F4.2** Cycle-detection in `effect` + `test/signal-cycle.test.mjs`
141
+ - [x] **F4.3** `equals` option on `computed`
142
+ - [x] **F4.4** Directives: `unsafeHTML`, `ref`, `classMap`, `styleMap` in `src/html/bindings.ts` + public exports + `test/html-directives.test.mjs`.
143
+ - [x] **F4.5** `useForm`: async validators (`validateAsync`, field-level `validateAsync`, `validating`) + field arrays (`form.array()`, dotted paths, wildcard schema) + tests.
144
+ - [x] **F4.6** Router: scroll restoration + focus management
145
+ - [x] **F4.7** Router: `errorPage:` in manifest + error boundary
146
+ - [x] **F4.8** `src/head.ts`: guaranteed cleanup on navigation (`data-mado-head` removed before re-applying)
147
+ - [x] **F4.9** Tests for everything above: `test/computed-lazy.test.mjs` (F4.1/F4.3), `test/signal-cycle.test.mjs` (F4.2), `test/html-directives.test.mjs` (F4.4), `test/forms.test.mjs` (F4.5), `test/router-isolation.test.mjs` (F4.6), `test/router-error-boundary.test.mjs` (F4.7), `test/head.test.mjs` (F4.8). Final `typecheck + build + test` pass verified.
148
+
149
+ ### Phase 5 — Documentation (parallel to phases 2-4)
150
+ English docs for project layout, layouts, auth/API and deployment exist now.
151
+ The remaining work is deeper recipes plus translation sync.
152
+
153
+ - [x] **F5.1** `docs/en/10-app-architecture.md` (end-to-end admin)
154
+ - [x] **F5.2** `docs/en/14-testing.md`
155
+ - [x] **F5.3** `docs/en/15-error-handling.md`
156
+ - [x] **F5.4** `docs/en/16-bake-cookbook.md`
157
+ - [x] **F5.5** `AGENTS.md`: section "App architecture for LLM"
158
+ - [x] **F5.6** `llms.txt`: new anchors
159
+ - [x] **F5.7** ru/fr/uk translations for new docs (`10` through `16`)
160
+
161
+ ---
162
+
163
+ ## 5. Working loop
164
+
165
+ 1. Pick the first unchecked box.
166
+ 2. Implement it (small, focused change).
167
+ 3. Run `npm test` (and `npm run typecheck` when touching `src/`).
168
+ 4. Tick the box in this file in the same commit.
169
+ 5. Add a one-line entry under "Unreleased" in `CHANGELOG.md`.
170
+ 6. After each phase finishes, pause and review.
171
+
172
+ ## 6. Context-loss safety
173
+
174
+ - This file = ground truth on disk.
175
+ - `task_progress` in chat = current phase/task.
176
+ - Git commits tagged `[v1 Fx.y]` = time machine.
177
+
178
+ If future work resumes from this plan, treat it as archive context. New tasks
179
+ belong in `ROADMAP.md`, `TODO.md`, or a fresh tracker.
package/README.md CHANGED
@@ -19,6 +19,11 @@
19
19
 
20
20
  > A small native-web SPA framework you can read in an evening.
21
21
 
22
+ [![npm](https://img.shields.io/npm/v/@madojs/mado.svg)](https://www.npmjs.com/package/@madojs/mado)
23
+ [![CI](https://github.com/madojs/mado/actions/workflows/ci.yml/badge.svg)](https://github.com/madojs/mado/actions/workflows/ci.yml)
24
+ [![Browser Regression](https://github.com/madojs/mado/actions/workflows/browser.yml/badge.svg)](https://github.com/madojs/mado/actions/workflows/browser.yml)
25
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
26
+
22
27
  Mado is a thin TypeScript framework on top of the browser platform: Web
23
28
  Components, signals, tagged-template `html`, a router, resources, forms,
24
29
  context, persisted state and static prerender. No runtime dependencies, no
@@ -27,6 +32,12 @@ required bundler, no hidden build pipeline: `tsc → browser`.
27
32
  Mado (`窓`) means “window” in Japanese: a calm native-web window into an app,
28
33
  without dragging a whole frontend factory into the room.
29
34
 
35
+ Mado does not try to replace the browser platform. The browser already gives
36
+ us modules, custom elements, attributes, events, forms, CSS, URLs, history,
37
+ fetch and the DOM. Mado's job is to make those primitives comfortable enough
38
+ for small and serious applications, without taking away your understanding of
39
+ what is happening.
40
+
30
41
  ```txt
31
42
  Runtime budget after build:
32
43
  native ESM graph: ~60 KB raw, ~24 KB gzip across separate modules
@@ -80,12 +91,20 @@ enough for serious admin apps while remaining small and readable.
80
91
  npm exec --package @madojs/mado@latest -- mado init my-app
81
92
  cd my-app
82
93
  npm install
83
- npm run build
84
- npm run serve
94
+ npm run dev
95
+ ```
96
+
97
+ Use the admin starter when you want the blessed production shape out of the box:
98
+ layouts, guards, auth/API client, dev proxy, forms and a small admin shell.
99
+
100
+ ```bash
101
+ npm exec --package @madojs/mado@latest -- mado init dashboard --starter admin
102
+ cd dashboard
103
+ npm install
104
+ npm run dev
85
105
  ```
86
106
 
87
- Use the CRUD starter when you want a compact admin-style example with
88
- `resource()`, `mutation()`, `useForm()`, `each()` and `queryParam()`:
107
+ Use the CRUD starter when you want a compact resource/mutation/forms example:
89
108
 
90
109
  ```bash
91
110
  npm exec --package @madojs/mado@latest -- mado init my-app --starter crud
@@ -140,17 +159,19 @@ The developer convenience CLI is available as `mado`:
140
159
 
141
160
  ```bash
142
161
  mado init my-app
162
+ mado init dashboard --starter admin
143
163
  mado init my-app --starter crud
164
+ mado dev
144
165
  mado build
145
166
  mado typecheck
146
167
  mado test
168
+ mado release
169
+ mado preview
147
170
  mado serve basic
148
171
  mado dev showcase
149
172
  mado examples
150
173
  ```
151
174
 
152
- The CLI is useful before v1, but its command polish may still change.
153
-
154
175
  ## Documentation
155
176
 
156
177
  - [Language index](./docs/README.md)
@@ -170,6 +191,13 @@ Core topics:
170
191
  - [For backenders](./docs/en/06-for-backenders.md)
171
192
  - [LLM pitfalls](./docs/en/07-llm-pitfalls.md)
172
193
  - [Shadow DOM vs Light DOM](./docs/en/09-shadow-vs-light-dom.md)
194
+ - [App architecture](./docs/en/10-app-architecture.md)
195
+ - [Layouts](./docs/en/11-layouts.md)
196
+ - [Auth and API](./docs/en/12-auth-and-api.md)
197
+ - [Deployment](./docs/en/13-deployment.md)
198
+ - [Testing](./docs/en/14-testing.md)
199
+ - [Error handling](./docs/en/15-error-handling.md)
200
+ - [Bake cookbook](./docs/en/16-bake-cookbook.md)
173
201
 
174
202
  AI-agent entrypoints:
175
203
 
@@ -314,8 +342,19 @@ html`
314
342
  `;
315
343
  ```
316
344
 
317
- Validation is based on native HTML constraint validation plus optional custom
318
- `validate(values)`.
345
+ Validation is schema-based and intentionally close to native HTML constraints:
346
+ `required`, `min`, `max`, `pattern`, `type=email/url/number`, plus optional
347
+ custom `validate(values)`. Async validators and field arrays are available via
348
+ `validateAsync`, `validateField()` and `form.array("items")`.
349
+
350
+ Only the root import is the stable public API:
351
+
352
+ ```ts
353
+ import { html, component, signal } from "@madojs/mado";
354
+ ```
355
+
356
+ Deep imports may exist in the package for tooling and generated files, but they
357
+ are internal and can change before v1.
319
358
 
320
359
  ## Static HTML Without Hydration
321
360
 
@@ -326,16 +365,16 @@ Cloudflare Worker edge-prerender PoC in [`examples/cloudflare`](./examples/cloud
326
365
 
327
366
  ## Production Bundle
328
367
 
329
- Native ESM is the default development and demo path. When a bundled production
330
- artifact is useful, run:
368
+ Native ESM is the default development path. For production, use the one-command
369
+ release pipeline:
331
370
 
332
371
  ```bash
333
- npm run bundle
334
- npm run preview
372
+ mado release
373
+ mado preview
335
374
  ```
336
375
 
337
- `bundle` uses optional `esbuild` for code splitting, SRI, `.gz` and `.br`
338
- outputs. `preview` emulates the provided `nginx.conf` with `node:http`.
376
+ `release` runs typecheck, build, bundle, bake and public asset copy, then writes
377
+ the deployable artifact into `out/`. `preview` serves `out/` like a static host.
339
378
 
340
379
  ## Tests
341
380
 
package/ROADMAP.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Roadmap
2
2
 
3
- Mado is pre-v1. The goal is not to grow sideways, but to keep the runtime small,
4
- readable and reliable under real application pressure.
3
+ Mado is still pre-1.0, but the v0.6 product-surface push is complete. The goal
4
+ from here is not to grow sideways, but to keep the runtime small, readable and
5
+ reliable under real application pressure.
5
6
 
6
7
  ## Current Focus
7
8
 
@@ -12,13 +13,41 @@ readable and reliable under real application pressure.
12
13
  - Keep English as the public/default project language, with localized docs in
13
14
  `docs/ru`, `docs/fr` and `docs/uk`.
14
15
 
15
- ## Before v1
16
+ ## Completed in v0.6
17
+
18
+ - **Phase 1 — Repo-vs-app split.** Kill `examples/`-leakage from CLI and bake;
19
+ introduce `mado.config.json`; app-mode becomes the default for `mado bake`,
20
+ `mado bundle`, `mado preview`.
21
+ - **Phase 2 — One blessed way.** First-class `layout()` + nested manifest;
22
+ `Guard` API with `redirect`/`halt`; blessed `--starter admin` starter with
23
+ blessed `api`/`auth` recipes; docs for layouts and auth-and-api.
24
+ - **Phase 3 — Bake first-class + Release pipeline.** `mado release` as the
25
+ single deploy command (`dist` internal, `out` deployed); `mado dev` serves
26
+ baked routes inline; bake stops silently rendering `[object Object]`;
27
+ deployment doc with VPS / Cloudflare Pages / static-CDN recipes.
28
+ - **Phase 4 — Core hardening.** Computed GC + cycle-detection in `effect`;
29
+ template directives (`unsafeHTML`, `ref`, `classMap`, `styleMap`); async
30
+ validators and field-arrays in `useForm`; scroll restoration, focus
31
+ management and error boundary in the router; head cleanup on navigation.
32
+ - **Phase 5 — Documentation (parallel).** `10-app-architecture.md`,
33
+ `11-layouts.md`, `12-auth-and-api.md`, `13-deployment.md`, `14-testing.md`,
34
+ `15-error-handling.md`, `16-bake-cookbook.md`; AGENTS.md app-architecture
35
+ section; ru/fr/uk translations.
36
+
37
+ The detailed completed tracker lives in [`MADO_V1_PLAN.md`](./MADO_V1_PLAN.md).
38
+
39
+ ## Remaining Before 1.0
16
40
 
17
41
  - Browser compatibility pass across current Chrome, Edge, Firefox and Safari.
18
42
  - Accessibility pass for examples and common component patterns.
19
43
  - Public API audit: names, warnings, lifecycle rules, docs coverage.
20
- - Release hygiene: npm provenance, GitHub repo metadata, tags and changelog.
44
+ - Public exports audit: root import is stable; deep imports must either become
45
+ explicit public subpaths or remain clearly unsupported before v1.
46
+ - Release hygiene: npm provenance / Trusted Publishing, GitHub repo metadata,
47
+ tags and changelog.
21
48
  - Size reporting command or CI summary with ESM and bundled/minified budgets.
49
+ - Public demo site built with Mado: docs, CRUD starter and showcase as a live
50
+ proof instead of another README claim.
22
51
  - Real commercial app test: validate auth, forms, tables, resources, route
23
52
  transitions and long-lived sessions outside toy examples.
24
53
 
@@ -43,8 +72,10 @@ readable and reliable under real application pressure.
43
72
  | 2026-06-03 | v0.3 hardening | Nested template cleanup, stale async route guard, Shadow DOM link/prefetch tests, scroll behavior, `warnOnce`, component reconnect/style tests. |
44
73
  | 2026-06-05 | v0.4 showcase max | `examples/showcase` became a SaaS CRM pressure app with accounts, deals, activity, nested routes, context services and browser regression. |
45
74
  | 2026-06-06 | v0.5 project shape | Unified `mado` CLI, dev server logs, docs language skeleton, examples cleanup (`basic`, `tickets`, `showcase`, `cloudflare`). |
46
- | 2026-06-06 | Mado rebrand | Public package/import name `madojs`, CLI `mado`, brand/docs/examples updated, internal legacy markers cleaned. |
75
+ | 2026-06-06 | Mado rebrand | Public package/import name `@madojs/mado`, CLI `mado`, brand/docs/examples updated, internal legacy markers cleaned. |
47
76
  | 2026-06-06 | Public polish | English public surface, localized docs, translated code comments/examples/templates/GitHub files. |
77
+ | 2026-06-07 | First npm release | Published `@madojs/mado@0.5.0` with the `mado` CLI, minimal/crud starters, CI and release workflow. |
78
+ | 2026-06-09 | v0.6 product surface | App-mode CLI/config split, admin starter, release pipeline, core hardening, v1 recipe docs and localized docs. |
48
79
 
49
80
  ## Future Ideas
50
81