@madojs/mado 0.11.1 → 0.12.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 (219) hide show
  1. package/AGENTS.md +102 -25
  2. package/CHANGELOG.md +158 -1
  3. package/README.md +135 -172
  4. package/dist/src/component.d.ts +3 -2
  5. package/dist/src/component.js +98 -6
  6. package/dist/src/component.js.map +1 -1
  7. package/dist/src/css.js +34 -5
  8. package/dist/src/css.js.map +1 -1
  9. package/dist/src/head.d.ts +6 -6
  10. package/dist/src/head.js +6 -6
  11. package/dist/src/html/parser.d.ts +1 -1
  12. package/dist/src/html/parser.js +1 -1
  13. package/dist/src/html/template.js +24 -10
  14. package/dist/src/html/template.js.map +1 -1
  15. package/dist/src/index.d.ts +8 -4
  16. package/dist/src/index.js +13 -3
  17. package/dist/src/index.js.map +1 -1
  18. package/dist/src/page.d.ts +62 -28
  19. package/dist/src/page.js +5 -0
  20. package/dist/src/page.js.map +1 -1
  21. package/dist/src/resource.js +2 -1
  22. package/dist/src/resource.js.map +1 -1
  23. package/dist/src/router/base.d.ts +65 -0
  24. package/dist/src/router/base.js +168 -0
  25. package/dist/src/router/base.js.map +1 -0
  26. package/dist/src/router/manifest.js +75 -31
  27. package/dist/src/router/manifest.js.map +1 -1
  28. package/dist/src/router/match.d.ts +16 -2
  29. package/dist/src/router/match.js +41 -1
  30. package/dist/src/router/match.js.map +1 -1
  31. package/dist/src/router/navigation.js +58 -9
  32. package/dist/src/router/navigation.js.map +1 -1
  33. package/dist/src/static-runtime.d.ts +81 -0
  34. package/dist/src/static-runtime.js +209 -0
  35. package/dist/src/static-runtime.js.map +1 -0
  36. package/dist/src/vite/index.d.ts +31 -3
  37. package/dist/src/vite/index.js +49 -18
  38. package/dist/src/vite/index.js.map +1 -1
  39. package/docs/README.md +5 -8
  40. package/docs/architecture/adr/0001-browser-static-snapshots.md +132 -0
  41. package/docs/en/00-the-mado-way.md +1 -1
  42. package/docs/en/01-quickstart.md +183 -0
  43. package/docs/en/10-pages-and-components.md +271 -0
  44. package/docs/en/11-templates-and-signals.md +211 -0
  45. package/docs/en/12-routing.md +229 -0
  46. package/docs/en/13-data.md +225 -0
  47. package/docs/en/14-forms.md +244 -0
  48. package/docs/en/15-static-snapshots.md +181 -0
  49. package/docs/en/{10-app-architecture.md → 16-app-architecture.md} +53 -2
  50. package/docs/en/{13-deployment.md → 20-deployment.md} +59 -10
  51. package/docs/en/{14-testing.md → 22-testing.md} +6 -5
  52. package/docs/en/23-cookbook.md +292 -0
  53. package/docs/en/{18-api-freeze-map.md → 30-api-freeze-map.md} +12 -3
  54. package/docs/en/{20-v1-stability.md → 32-v1-stability.md} +3 -3
  55. package/docs/en/40-llm-guide.md +776 -0
  56. package/docs/en/{06-for-backenders.md → 41-for-backenders.md} +15 -16
  57. package/docs/en/{05-why-mado.md → 42-why-mado.md} +1 -1
  58. package/docs/en/README.md +97 -27
  59. package/docs/recipes/nginx/Containerfile +26 -0
  60. package/docs/recipes/nginx/nginx.conf +42 -0
  61. package/llms.txt +246 -211
  62. package/package.json +17 -10
  63. package/scripts/bake.mjs +4 -569
  64. package/scripts/cli/generate.mjs +55 -5
  65. package/scripts/cli/help.mjs +11 -5
  66. package/scripts/cli/index.mjs +20 -4
  67. package/scripts/cli/init.mjs +7 -2
  68. package/scripts/cli/release.mjs +20 -68
  69. package/scripts/docs-lint.mjs +170 -0
  70. package/scripts/package-smoke.mjs +67 -9
  71. package/scripts/preview.mjs +95 -6
  72. package/scripts/size-budget.mjs +5 -1
  73. package/scripts/static/browser.mjs +654 -0
  74. package/scripts/static/discover.mjs +281 -0
  75. package/scripts/static/output.mjs +141 -0
  76. package/scripts/static/serialize.mjs +212 -0
  77. package/scripts/static/server.mjs +167 -0
  78. package/scripts/static.mjs +191 -0
  79. package/starters/default/README.md +57 -55
  80. package/starters/default/package.json +3 -9
  81. package/starters/default/src/app.routes.ts +20 -33
  82. package/starters/default/src/components/feature-card.component.ts +40 -0
  83. package/starters/default/src/components/live-counter.component.ts +57 -0
  84. package/starters/default/src/content/guides.ts +55 -0
  85. package/starters/default/src/main.ts +9 -13
  86. package/starters/default/src/pages/app.page.ts +41 -0
  87. package/starters/default/src/pages/guide.page.ts +40 -0
  88. package/starters/default/src/pages/home.page.ts +49 -0
  89. package/starters/default/src/pages/not-found.page.ts +18 -0
  90. package/starters/default/src/styles/document.css +39 -0
  91. package/starters/default/src/styles/reset.css +37 -0
  92. package/starters/default/src/styles/tokens.css +30 -0
  93. package/starters/default/src/styles.d.ts +3 -1
  94. package/starters/default/src/vite-env.d.ts +1 -1
  95. package/starters/default/vite.config.ts +14 -1
  96. package/starters/modular/README.md +142 -0
  97. package/starters/modular/index.html +13 -0
  98. package/starters/modular/package.json +30 -0
  99. package/starters/modular/src/app.routes.ts +39 -0
  100. package/starters/{default → modular}/src/layouts/app-shell.layout.ts +8 -5
  101. package/starters/{default → modular}/src/layouts/auth-shell.layout.ts +3 -3
  102. package/starters/modular/src/main.ts +16 -0
  103. package/starters/{default → modular}/src/modules/billing/pages/invoices-list.page.ts +3 -3
  104. package/starters/{default → modular}/src/modules/home/home.page.ts +5 -7
  105. package/starters/modular/src/modules/home/not-found.page.ts +14 -0
  106. package/starters/modular/src/styles.d.ts +1 -0
  107. package/starters/modular/src/vite-env.d.ts +1 -0
  108. package/starters/modular/tsconfig.json +24 -0
  109. package/starters/modular/vite.config.ts +131 -0
  110. package/TODO.md +0 -79
  111. package/docs/en/01-routing.md +0 -152
  112. package/docs/en/02-project-layout.md +0 -124
  113. package/docs/en/03-static-bake.md +0 -249
  114. package/docs/en/04-ide-setup.md +0 -162
  115. package/docs/en/07-llm-pitfalls.md +0 -724
  116. package/docs/en/08-llm-zero-history-test.md +0 -56
  117. package/docs/en/09-shadow-vs-light-dom.md +0 -174
  118. package/docs/en/11-layouts.md +0 -113
  119. package/docs/en/12-auth-and-api.md +0 -124
  120. package/docs/en/16-bake-cookbook.md +0 -100
  121. package/docs/en/17-shadow-dom-forms.md +0 -192
  122. package/docs/fr/00-the-mado-way.md +0 -85
  123. package/docs/fr/01-routing.md +0 -120
  124. package/docs/fr/02-project-layout.md +0 -84
  125. package/docs/fr/03-static-bake.md +0 -289
  126. package/docs/fr/04-ide-setup.md +0 -162
  127. package/docs/fr/05-why-mado.md +0 -193
  128. package/docs/fr/06-for-backenders.md +0 -438
  129. package/docs/fr/07-llm-pitfalls.md +0 -625
  130. package/docs/fr/08-llm-zero-history-test.md +0 -38
  131. package/docs/fr/09-shadow-vs-light-dom.md +0 -65
  132. package/docs/fr/10-app-architecture.md +0 -138
  133. package/docs/fr/11-layouts.md +0 -47
  134. package/docs/fr/12-auth-and-api.md +0 -76
  135. package/docs/fr/13-deployment.md +0 -57
  136. package/docs/fr/14-testing.md +0 -41
  137. package/docs/fr/15-error-handling.md +0 -50
  138. package/docs/fr/16-bake-cookbook.md +0 -88
  139. package/docs/fr/17-shadow-dom-forms.md +0 -196
  140. package/docs/fr/18-api-freeze-map.md +0 -63
  141. package/docs/fr/19-reactivity-ordering.md +0 -97
  142. package/docs/fr/20-v1-stability.md +0 -88
  143. package/docs/fr/README.md +0 -27
  144. package/docs/ru/00-the-mado-way.md +0 -84
  145. package/docs/ru/01-routing.md +0 -119
  146. package/docs/ru/02-project-layout.md +0 -84
  147. package/docs/ru/03-static-bake.md +0 -250
  148. package/docs/ru/04-ide-setup.md +0 -144
  149. package/docs/ru/05-why-mado.md +0 -193
  150. package/docs/ru/06-for-backenders.md +0 -428
  151. package/docs/ru/07-llm-pitfalls.md +0 -624
  152. package/docs/ru/08-llm-zero-history-test.md +0 -57
  153. package/docs/ru/09-shadow-vs-light-dom.md +0 -63
  154. package/docs/ru/10-app-architecture.md +0 -152
  155. package/docs/ru/11-layouts.md +0 -47
  156. package/docs/ru/12-auth-and-api.md +0 -75
  157. package/docs/ru/13-deployment.md +0 -66
  158. package/docs/ru/14-testing.md +0 -50
  159. package/docs/ru/15-error-handling.md +0 -56
  160. package/docs/ru/16-bake-cookbook.md +0 -95
  161. package/docs/ru/17-shadow-dom-forms.md +0 -193
  162. package/docs/ru/18-api-freeze-map.md +0 -64
  163. package/docs/ru/19-reactivity-ordering.md +0 -95
  164. package/docs/ru/20-v1-stability.md +0 -82
  165. package/docs/ru/README.md +0 -25
  166. package/docs/uk/00-the-mado-way.md +0 -82
  167. package/docs/uk/01-routing.md +0 -76
  168. package/docs/uk/02-project-layout.md +0 -73
  169. package/docs/uk/03-static-bake.md +0 -48
  170. package/docs/uk/04-ide-setup.md +0 -26
  171. package/docs/uk/05-why-mado.md +0 -34
  172. package/docs/uk/06-for-backenders.md +0 -55
  173. package/docs/uk/07-llm-pitfalls.md +0 -145
  174. package/docs/uk/08-llm-zero-history-test.md +0 -34
  175. package/docs/uk/09-shadow-vs-light-dom.md +0 -58
  176. package/docs/uk/10-app-architecture.md +0 -97
  177. package/docs/uk/11-layouts.md +0 -47
  178. package/docs/uk/12-auth-and-api.md +0 -70
  179. package/docs/uk/13-deployment.md +0 -40
  180. package/docs/uk/14-testing.md +0 -34
  181. package/docs/uk/15-error-handling.md +0 -32
  182. package/docs/uk/16-bake-cookbook.md +0 -36
  183. package/docs/uk/17-shadow-dom-forms.md +0 -193
  184. package/docs/uk/18-api-freeze-map.md +0 -61
  185. package/docs/uk/19-reactivity-ordering.md +0 -95
  186. package/docs/uk/20-v1-stability.md +0 -83
  187. package/docs/uk/README.md +0 -27
  188. package/starters/default/src/modules/home/not-found.page.ts +0 -11
  189. /package/docs/en/{15-error-handling.md → 21-error-handling.md} +0 -0
  190. /package/docs/en/{19-reactivity-ordering.md → 31-reactivity-ordering.md} +0 -0
  191. /package/starters/{default → modular}/.editorconfig +0 -0
  192. /package/starters/{default → modular}/eslint.config.mjs +0 -0
  193. /package/starters/{default → modular}/public/favicon.svg +0 -0
  194. /package/starters/{default → modular}/src/modules/auth/_contracts/auth-api.types.ts +0 -0
  195. /package/starters/{default → modular}/src/modules/auth/auth.connector.ts +0 -0
  196. /package/starters/{default → modular}/src/modules/auth/auth.guard.ts +0 -0
  197. /package/starters/{default → modular}/src/modules/auth/auth.public.ts +0 -0
  198. /package/starters/{default → modular}/src/modules/auth/auth.routes.ts +0 -0
  199. /package/starters/{default → modular}/src/modules/auth/auth.service.ts +0 -0
  200. /package/starters/{default → modular}/src/modules/auth/auth.types.ts +0 -0
  201. /package/starters/{default → modular}/src/modules/auth/login.page.ts +0 -0
  202. /package/starters/{default → modular}/src/modules/billing/_contracts/stripe.types.ts +0 -0
  203. /package/starters/{default → modular}/src/modules/billing/api/stripe.connector.ts +0 -0
  204. /package/starters/{default → modular}/src/modules/billing/billing.public.ts +0 -0
  205. /package/starters/{default → modular}/src/modules/billing/billing.routes.ts +0 -0
  206. /package/starters/{default → modular}/src/modules/billing/billing.types.ts +0 -0
  207. /package/starters/{default → modular}/src/modules/billing/components/invoice-status-badge.component.ts +0 -0
  208. /package/starters/{default → modular}/src/modules/billing/data/invoices.resource.ts +0 -0
  209. /package/starters/{default → modular}/src/modules/billing/pages/invoice-detail.page.ts +0 -0
  210. /package/starters/{default → modular}/src/shared/http/http-client.ts +0 -0
  211. /package/starters/{default → modular}/src/shared/http/http-error.ts +0 -0
  212. /package/starters/{default → modular}/src/shared/http/interceptors.ts +0 -0
  213. /package/starters/{default → modular}/src/shared/lib/format-date.ts +0 -0
  214. /package/starters/{default → modular}/src/shared/styles/content.css +0 -0
  215. /package/starters/{default → modular}/src/shared/styles/reset.css +0 -0
  216. /package/starters/{default → modular}/src/shared/styles/shell.css +0 -0
  217. /package/starters/{default → modular}/src/shared/styles/tokens.css +0 -0
  218. /package/starters/{default → modular}/src/shared/ui/x-button.component.ts +0 -0
  219. /package/starters/{default → modular}/src/shared/ui/x-spinner.component.ts +0 -0
package/AGENTS.md CHANGED
@@ -3,14 +3,20 @@
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
5
  >
6
- > / `TODO.md` unless the user explicitly resumes that tracker.
6
+ > Skip `TODO.md` unless the user explicitly resumes that tracker.
7
7
 
8
8
  ## Project at a glance
9
9
 
10
- - **Mado** — a calm browser-native SPA framework for internal tools, admin panels and business apps.
10
+ - **Mado** — a calm native-first web framework for both static sites
11
+ and live SPAs. One Web Component model, one page model, one release
12
+ command.
13
+ - Current stable release: **0.12.0**.
11
14
  - Built on Web Components + signals + tagged-template `html`.
12
- - Zero runtime dependencies. Generated apps use dev tooling (`typescript`,
13
- `vite`, `linkedom`) for dev/build/bake/release.
15
+ - **Vite is the canonical transport** for development, build and the
16
+ static snapshot pipeline. Generated apps depend on `typescript`,
17
+ `vite` and `playwright-core` (the last only for `mado release`,
18
+ which captures real Chromium-rendered HTML).
19
+ - Zero runtime dependencies (Vite is dev/build tooling, not bundled).
14
20
  - Small TypeScript core in `src/`; production size budgets are enforced in CI.
15
21
 
16
22
  ## HARD RULES — violation = bug
@@ -384,16 +390,54 @@ Rules:
384
390
  - Tiny leaf components used everywhere → importing in `main.ts` is acceptable.
385
391
  - Do **not** bulk-import every component "just in case".
386
392
 
387
- ### 14. Bakemeta shell, not SSR/SSG runtime
393
+ ### 14. Static snapshots browser-rendered, not SSR/SSG
388
394
 
389
- `mado bake` is a static meta-shell/prerender pass for SEO and first paint. It is
390
- not SSR with hydration and not a Next-style SSG runtime.
395
+ `mado static` (normally invoked through `mado release`) captures real
396
+ HTML by navigating each page in a headless Chromium and serialising
397
+ the resulting DOM, including the Shadow DOM through Declarative Shadow
398
+ DOM (DSD). On first paint the live SPA **atomically replaces** the
399
+ static tree — there is no hydration protocol, no node reconciliation
400
+ and no per-attribute diffing.
391
401
 
392
- - Baked HTML must be deterministic from `params`, `bake.data`, and plain values.
393
- - Do not rely on browser-only effects, timers, relative `fetch`, or keyed
394
- runtime directives such as `each()` during bake.
395
- - Use `page({ head, bake })` for meta/JSON-LD/sitemap data; render dynamic,
396
- personalized, real-time, or auth-dependent content in the client SPA.
402
+ A page opts in by declaring `static` on `page({ ... })`:
403
+
404
+ ```ts
405
+ // Static landing page
406
+ export default page({
407
+ static: true,
408
+ title: "Home",
409
+ head: () => ({ description: "Public landing" }),
410
+ view: () => html`<main><h1>Hello</h1></main>`,
411
+ });
412
+
413
+ // Dynamic static route
414
+ export default page({
415
+ static: {
416
+ paths: async () => [{ slug: "alpha" }, { slug: "beta" }],
417
+ initialData: async ({ slug }) => loadGuide(slug),
418
+ },
419
+ title: ({ slug }) => `Guide: ${slug}`,
420
+ view: (ctx) => html`<article>${ctx.data}</article>`,
421
+ });
422
+ ```
423
+
424
+ Important constraints:
425
+
426
+ - Static pages cannot use guards (route- or layout-level) — they are
427
+ public by definition.
428
+ - `paths()` and `initialData()` run at discovery AND ship in the
429
+ client bundle. Keep them browser-safe; never read secrets.
430
+ - Wildcard routes (`*`) cannot be static.
431
+ - The `static` discovery uses Vite SSR as a control plane only;
432
+ nothing is rendered in Node. The actual capture happens in
433
+ headless Chromium.
434
+
435
+ <!-- docs-lint:allow-legacy-mention -->
436
+ There is no `bake`, no `bake.paths`, no `bake.data`, no
437
+ `bake.revalidate`, no `npm run bake`, no `linkedom` renderer, no
438
+ "meta-shell". Those names refer to a removed system; do not generate
439
+ them. If you see them in older docs, treat them as obsolete.
440
+ <!-- /docs-lint:allow-legacy-mention -->
397
441
 
398
442
  ## SOFT GUIDELINES — recommended, but not critical
399
443
 
@@ -409,19 +453,52 @@ not SSR with hydration and not a Next-style SSG runtime.
409
453
 
410
454
  ## Project structure
411
455
 
456
+ Two official starters target the same Mado runtime:
457
+
412
458
  ```
459
+ # universal starter (default — `mado init my-app`)
460
+ src/
461
+ ├── main.ts
462
+ ├── app.routes.ts
463
+ ├── pages/ ← one *.page.ts per route, light DOM
464
+ ├── components/ ← reusable Web Components (Shadow DOM)
465
+ ├── content/ ← static content (guides, etc.)
466
+ └── styles/
467
+
468
+ # modular starter (`mado init my-app --starter modular`)
413
469
  src/
414
- ├── main.ts ← entry: mount to #app
415
- ├── app.routes.ts ← app map, exports `manifest` + default routes(...)
416
- ├── layouts/ ← app-zone layout modules (`page({ child })`)
417
- ├── shared/ ← ui, http, lib, styles
418
- └── modules/ ← bounded contexts with pages/data/api/services
470
+ ├── main.ts
471
+ ├── app.routes.ts
472
+ ├── layouts/ stateless app-zone shells (`page({ child })`)
473
+ ├── shared/ ← ui, http, lib, styles
474
+ └── modules/ ← bounded contexts with pages/data/api/services
419
475
  ```
420
476
 
477
+ The modular starter ships a dev-only mock API in `vite.config.ts`
478
+ (`/api/auth/*`, `/api/billing/*`). Disable with `MADO_MOCK_API=0`
479
+ or remove the `devApiMock()` plugin before pointing at a real backend.
480
+
481
+ ## Internal links — always `routeUrl()`
482
+
483
+ Vite's `base` flows automatically into `appBase` and `routeUrl()`. App
484
+ code MUST use `routeUrl()` for every internal anchor so the URL stays
485
+ correct under `/`, `/mado/` or any sub-path deployment, and MUST opt
486
+ in with `data-link` for SPA navigation:
487
+
488
+ ```ts
489
+ import { routeUrl } from "@madojs/mado";
490
+
491
+ html`<a data-link href=${routeUrl("/users/42")}>User</a>`;
492
+ html`<a data-link href=${routeUrl("/")}>Home</a>`; // → "/mado/" under base
493
+ ```
494
+
495
+ `navigate("/users/42")` for programmatic navigation. Both accept route
496
+ paths (no base) and apply the active base internally.
497
+
421
498
  ## App architecture for LLM
422
499
 
423
500
  When generating an app, prefer the blessed production shape from
424
- `docs/en/10-app-architecture.md` and the `starters/default/` example:
501
+ `docs/en/16-app-architecture.md` and the `starters/default/` example:
425
502
 
426
503
  - `src/main.ts` mounts `routesApi.view` and imports only global styles,
427
504
  providers, and tiny shared components.
@@ -445,13 +522,13 @@ When generating an app, prefer the blessed production shape from
445
522
  | How does the router work? | `src/router/` |
446
523
  | How does resource + cache work? | `src/resource.ts` (297 lines) |
447
524
  | How do forms work? | `src/forms.ts` (212 lines) |
448
- | How should an app be structured? | `docs/en/10-app-architecture.md` |
449
- | How should errors be handled? | `docs/en/15-error-handling.md` |
450
- | How should bake be used? | `docs/en/16-bake-cookbook.md` |
451
- | What API is stable? | `docs/en/18-api-freeze-map.md` |
452
- | What ordering is guaranteed? | `docs/en/19-reactivity-ordering.md` |
453
- | What does v1 stability mean? | `docs/en/20-v1-stability.md` |
454
- | When something goes wrong | `docs/en/07-llm-pitfalls.md` |
525
+ | How should an app be structured? | `docs/en/16-app-architecture.md` |
526
+ | How should errors be handled? | `docs/en/21-error-handling.md` |
527
+ | How should static snapshots be used? | `docs/en/15-static-snapshots.md` / `docs/en/23-cookbook.md` |
528
+ | What API is stable? | `docs/en/30-api-freeze-map.md` |
529
+ | What ordering is guaranteed? | `docs/en/31-reactivity-ordering.md` |
530
+ | What does v1 stability mean? | `docs/en/32-v1-stability.md` |
531
+ | When something goes wrong | `docs/en/40-llm-guide.md` |
455
532
 
456
533
  ## Before committing
457
534
 
package/CHANGELOG.md CHANGED
@@ -1,6 +1,163 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 0.12.0 - 2026-06-24
4
+
5
+ ### Stable polish
6
+
7
+ Two rounds of post-rc polish for the 0.12.0 cut:
8
+
9
+ #### Pre-merge fixes (carried over from the rc.1 review)
10
+
11
+ - **Router base/prefetch.** `routeUrl()` on `"/"` and hover-prefetch
12
+ on Vite `base` deployments now resolve correctly under any sub-path
13
+ (`/`, `/mado/`, `/admin/`).
14
+ - **`mado static` cleanup.** No more race between `process.exit` and
15
+ capture; canonical `<link>` is stripped on SPA navigation into pages
16
+ that don't declare their own head metadata.
17
+ - **Discovery.** `mado static` no longer bypasses `fatal()` when
18
+ Vite SSR import fails; failures abort the snapshot.
19
+ - **Modular starter.** All internal anchors flow through
20
+ `routeUrl()` + `data-link`; generators are context-aware and
21
+ refuse to overwrite existing files.
22
+ - **`package:smoke`.** Now exercises both the default and modular
23
+ starters end to end.
24
+ - **Release publishing.** `next` versions stay on the `next`
25
+ dist-tag; `latest` is reserved for stable cuts. The release and
26
+ weekly workflows install a pinned Playwright Chromium so static
27
+ snapshots never silently skip on CI.
28
+ - **`mado preview`.** Prints the active base URL so users browsing
29
+ under a sub-path see the right entrypoint.
30
+ - **`TODO.md` / `CONTRIBUTING.md` / `package.json#files`** trimmed
31
+ to match the post-rc reality.
32
+
33
+ #### Documentation reorganisation
34
+
35
+ `docs/en/` was rewritten so users (and LLMs) get one happy path:
36
+ **"don't think `shadow: true` vs `shadow: false`; pick `page()` for
37
+ URLs and `component()` for reusable widgets."**
38
+
39
+ - **New flagship doc** `docs/en/10-pages-and-components.md` —
40
+ "the one rule": `page()` for routes, `component()` for reusable
41
+ `<x-tag>`s. Anti-patterns + decision table + `{ shadow: false }`
42
+ escape hatch.
43
+ - **New numbering** groups docs into Start here / Concepts /
44
+ Production / Reference / Meta. Migration map for stale links is in
45
+ `docs/en/README.md`.
46
+ - **Consolidated pages** —
47
+ `11-templates-and-signals.md` (NEW), `12-routing.md` (merges old
48
+ routing + layouts), `13-data.md` (merges old data + auth/api),
49
+ `14-forms.md` (merges old forms + Shadow-DOM forms),
50
+ `15-static-snapshots.md`, `16-app-architecture.md` (merges old
51
+ project-layout), `01-quickstart.md` (merges old IDE-setup),
52
+ `40-llm-guide.md` (merges old pitfalls + zero-history test).
53
+ - **Deleted** `docs/fr`, `docs/uk`, `docs/ru` — English-only since
54
+ v0.12. Several legacy `docs/en/*` files were removed; their
55
+ content lives in the consolidated pages.
56
+ - **Truth pass on retained prose.** Killed obsolete claims:
57
+ no more "tsc-only", "no bundler", "SSE reload", "tsc → browser",
58
+ "edge prerender", "import maps". Vite is consistently named as
59
+ the canonical transport.
60
+ - **`scripts/docs-lint.mjs`** now also blocks the obsolete vocabulary
61
+ above and any links to renamed `docs/en/*` filenames in active
62
+ docs; the migration table in `docs/en/README.md` is wrapped in a
63
+ `docs-lint:allow-legacy-mention` block.
64
+
65
+ ## 0.12.0-rc.1 - 2026-06-22
66
+
67
+ The unified pre-merge release. Mado is no longer "a calm browser-native
68
+ SPA framework for internal tools"; it becomes **"a calm native-first
69
+ web framework for sites and apps"** with one component model end to end.
70
+ The full plan is preserved as
71
+ [ADR 0001 — Browser-rendered static snapshots](./docs/architecture/adr/0001-browser-static-snapshots.md).
72
+
73
+ ### Positioning
74
+
75
+ - New tagline: **One component model. One page model. One release command.**
76
+ - README, `package.json` (description + keywords), CLI help and starter
77
+ READMEs all updated to the sites-and-apps positioning.
78
+ - `MADO_UNIFIED_PRE_MERGE_PLAN.MD` moved to
79
+ `docs/architecture/adr/0001-browser-static-snapshots.md`.
80
+
81
+ ### Added
82
+
83
+ - **`src/router/base.ts`** — single source of truth for the Vite base.
84
+ Exports `appBase`, `normalizeBase`, `stripBase`, `withBase` and the
85
+ new public `routeUrl()` helper. The runtime reads
86
+ `import.meta.env.BASE_URL` once and exposes it through these helpers
87
+ so every internal link is base-aware without any application
88
+ configuration.
89
+ - **Production-served snapshot → live takeover E2E gate.**
90
+ `test/static/dsd-takeover.test.mjs` now scaffolds a real app, runs
91
+ `mado release`, hosts it through `mado preview` and asserts the
92
+ takeover contract through headless Chromium with strict
93
+ no-`.catch()` assertions.
94
+ - **Base-path fixture.** `test/static/base-path.test.mjs` proves the
95
+ whole `/mado/` deployment shape end to end: build, sitemap, capture,
96
+ preview redirects, SPA fallback, runtime stripBase/withBase.
97
+ - **Canonical / `og:url` auto-fallback.** When a page does not declare
98
+ either, the snapshot pipeline derives an absolute
99
+ `site + base + pathname` URL, deduplicates duplicates and rejects
100
+ localhost / capture-origin values.
101
+ - **Strict `JsonValue` validator** with path-aware errors. Date / Map /
102
+ Set / class instances / undefined / NaN / Infinity / cycles all fail
103
+ the build with the exact JSON path that broke
104
+ (`[mado:static] /products/keyboard: seed.product.createdAt is Date`).
105
+ - **Universal default starter** (`mado init my-app`). ~15 source
106
+ files, no backend required, demonstrates one Shadow Component shared
107
+ between a static landing page and a live SPA route.
108
+ - **Modular starter preserved** (`mado init my-app --starter modular`)
109
+ as the long-lived business-application reference architecture.
110
+ - **HTTP policy documented** in `scripts/static/browser.mjs`: fatal
111
+ vs ignored vs quality-hint classes are explicit, with bounded
112
+ timeouts for fonts and paint frames.
113
+ - **`scripts/docs-lint.mjs`** refuses the old vocabulary in current
114
+ docs (page.bake, mado bake, out/baked, "No Vite required",
115
+ "internal tools only") while still allowing it in migration guides
116
+ and ADRs.
117
+ - **Required CI gate** `.github/workflows/ci.yml → static-snapshot`
118
+ installs Playwright-managed Chromium with
119
+ `npx playwright install --with-deps chromium` and runs the static
120
+ tests under `MADO_REQUIRE_BROWSER=1` so they cannot silently skip.
121
+
122
+ ### Changed (breaking)
123
+
124
+ - **`mado build`** in app contexts now performs a Vite production
125
+ build of the deployable SPA (`vite build`). Inside the framework
126
+ repository it still calls `tsc`. The internal tsc compile is
127
+ exposed via `npm run build` in the repo. Use `mado typecheck` if
128
+ you only wanted `tsc --noEmit`.
129
+ - **`out/_mado/build.json`** is dropped from the final release
130
+ artifact. It is internal CLI plumbing emitted by the
131
+ `@madojs/mado/vite` plugin so `mado static` and `mado preview` can
132
+ read the resolved Vite base/site without parsing `vite.config.ts`.
133
+ `mado preview` now derives the base from the build bridge OR from
134
+ the asset prefix in `out/index.html`, so the preview works on the
135
+ shipped artifact.
136
+ - **Static output staging.** `out/_mado/spa.html` is no longer touched
137
+ until every static route captures cleanly; a failure mid-pipeline
138
+ leaves the previous deployment intact. `cleanupTemp()` always runs
139
+ in `finally`.
140
+ - **`whenStable()` phase-bounded.** The runtime now waits for
141
+ routeReady (cap: 15s) and tracked resources (cap: 15s) separately
142
+ so timeout diagnostics name the failing phase. Fonts and paint
143
+ frames are best-effort with bounded timeouts (5s / 1s); on timeout
144
+ the snapshot proceeds with a diagnostic instead of failing.
145
+ - **Browser launch order.** `chromium.launch()` (Playwright-managed)
146
+ is tried *before* `channel: "chrome"` so CI determinism does not
147
+ depend on whatever branded Chrome happens to be installed.
148
+
149
+ ### Migration
150
+
151
+ | Before | After |
152
+ |---|---|
153
+ | `page.bake` | `page.static` |
154
+ | `mado bake` | `mado static` |
155
+ | `out/baked/...` | `out/<route>/index.html` |
156
+ | `#bake` data | `data-mado-static-data` script |
157
+ | `shadow: false` for SEO | open Shadow DOM (snapshotted as DSD) |
158
+ | `site` was optional | required for any `static` route |
159
+ | Vite plugin optional | canonical transport |
160
+ | `mado build` ≈ `tsc` | `mado build` ≈ `vite build` |
4
161
 
5
162
  ## 0.11.1 - 2026-06-21
6
163