@madojs/mado 0.11.0 → 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 (221) hide show
  1. package/AGENTS.md +102 -25
  2. package/CHANGELOG.md +185 -1
  3. package/README.md +137 -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/bindings.js +3 -3
  12. package/dist/src/html/bindings.js.map +1 -1
  13. package/dist/src/html/parser.d.ts +1 -1
  14. package/dist/src/html/parser.js +1 -1
  15. package/dist/src/html/template.js +24 -10
  16. package/dist/src/html/template.js.map +1 -1
  17. package/dist/src/index.d.ts +8 -4
  18. package/dist/src/index.js +13 -3
  19. package/dist/src/index.js.map +1 -1
  20. package/dist/src/page.d.ts +62 -28
  21. package/dist/src/page.js +5 -0
  22. package/dist/src/page.js.map +1 -1
  23. package/dist/src/resource.js +2 -1
  24. package/dist/src/resource.js.map +1 -1
  25. package/dist/src/router/base.d.ts +65 -0
  26. package/dist/src/router/base.js +168 -0
  27. package/dist/src/router/base.js.map +1 -0
  28. package/dist/src/router/manifest.js +75 -31
  29. package/dist/src/router/manifest.js.map +1 -1
  30. package/dist/src/router/match.d.ts +16 -2
  31. package/dist/src/router/match.js +41 -1
  32. package/dist/src/router/match.js.map +1 -1
  33. package/dist/src/router/navigation.js +58 -9
  34. package/dist/src/router/navigation.js.map +1 -1
  35. package/dist/src/static-runtime.d.ts +81 -0
  36. package/dist/src/static-runtime.js +209 -0
  37. package/dist/src/static-runtime.js.map +1 -0
  38. package/dist/src/vite/index.d.ts +31 -3
  39. package/dist/src/vite/index.js +49 -18
  40. package/dist/src/vite/index.js.map +1 -1
  41. package/docs/README.md +5 -8
  42. package/docs/architecture/adr/0001-browser-static-snapshots.md +132 -0
  43. package/docs/en/00-the-mado-way.md +1 -1
  44. package/docs/en/01-quickstart.md +183 -0
  45. package/docs/en/10-pages-and-components.md +271 -0
  46. package/docs/en/11-templates-and-signals.md +211 -0
  47. package/docs/en/12-routing.md +229 -0
  48. package/docs/en/13-data.md +225 -0
  49. package/docs/en/14-forms.md +244 -0
  50. package/docs/en/15-static-snapshots.md +181 -0
  51. package/docs/en/{10-app-architecture.md → 16-app-architecture.md} +53 -2
  52. package/docs/en/{13-deployment.md → 20-deployment.md} +59 -10
  53. package/docs/en/{14-testing.md → 22-testing.md} +6 -5
  54. package/docs/en/23-cookbook.md +292 -0
  55. package/docs/en/{18-api-freeze-map.md → 30-api-freeze-map.md} +12 -3
  56. package/docs/en/{20-v1-stability.md → 32-v1-stability.md} +3 -3
  57. package/docs/en/40-llm-guide.md +776 -0
  58. package/docs/en/{06-for-backenders.md → 41-for-backenders.md} +15 -16
  59. package/docs/en/{05-why-mado.md → 42-why-mado.md} +1 -1
  60. package/docs/en/README.md +97 -27
  61. package/docs/recipes/nginx/Containerfile +26 -0
  62. package/docs/recipes/nginx/nginx.conf +42 -0
  63. package/llms.txt +246 -211
  64. package/package.json +17 -10
  65. package/scripts/bake.mjs +4 -568
  66. package/scripts/cli/generate.mjs +55 -5
  67. package/scripts/cli/help.mjs +11 -5
  68. package/scripts/cli/index.mjs +20 -4
  69. package/scripts/cli/init.mjs +7 -2
  70. package/scripts/cli/release.mjs +20 -68
  71. package/scripts/docs-lint.mjs +170 -0
  72. package/scripts/package-smoke.mjs +67 -9
  73. package/scripts/preview.mjs +95 -6
  74. package/scripts/size-budget.mjs +5 -1
  75. package/scripts/static/browser.mjs +654 -0
  76. package/scripts/static/discover.mjs +281 -0
  77. package/scripts/static/output.mjs +141 -0
  78. package/scripts/static/serialize.mjs +212 -0
  79. package/scripts/static/server.mjs +167 -0
  80. package/scripts/static.mjs +191 -0
  81. package/starters/default/README.md +57 -55
  82. package/starters/default/package.json +3 -9
  83. package/starters/default/src/app.routes.ts +20 -33
  84. package/starters/default/src/components/feature-card.component.ts +40 -0
  85. package/starters/default/src/components/live-counter.component.ts +57 -0
  86. package/starters/default/src/content/guides.ts +55 -0
  87. package/starters/default/src/main.ts +9 -13
  88. package/starters/default/src/pages/app.page.ts +41 -0
  89. package/starters/default/src/pages/guide.page.ts +40 -0
  90. package/starters/default/src/pages/home.page.ts +49 -0
  91. package/starters/default/src/pages/not-found.page.ts +18 -0
  92. package/starters/default/src/styles/document.css +39 -0
  93. package/starters/default/src/styles/reset.css +37 -0
  94. package/starters/default/src/styles/tokens.css +30 -0
  95. package/starters/default/src/styles.d.ts +3 -1
  96. package/starters/default/src/vite-env.d.ts +1 -1
  97. package/starters/default/vite.config.ts +14 -1
  98. package/starters/modular/README.md +142 -0
  99. package/starters/modular/index.html +13 -0
  100. package/starters/modular/package.json +30 -0
  101. package/starters/modular/src/app.routes.ts +39 -0
  102. package/starters/{default → modular}/src/layouts/app-shell.layout.ts +8 -5
  103. package/starters/{default → modular}/src/layouts/auth-shell.layout.ts +3 -3
  104. package/starters/modular/src/main.ts +16 -0
  105. package/starters/{default → modular}/src/modules/billing/pages/invoices-list.page.ts +3 -3
  106. package/starters/{default → modular}/src/modules/home/home.page.ts +5 -7
  107. package/starters/modular/src/modules/home/not-found.page.ts +14 -0
  108. package/starters/modular/src/styles.d.ts +1 -0
  109. package/starters/modular/src/vite-env.d.ts +1 -0
  110. package/starters/modular/tsconfig.json +24 -0
  111. package/starters/modular/vite.config.ts +131 -0
  112. package/TODO.md +0 -79
  113. package/docs/en/01-routing.md +0 -152
  114. package/docs/en/02-project-layout.md +0 -124
  115. package/docs/en/03-static-bake.md +0 -249
  116. package/docs/en/04-ide-setup.md +0 -162
  117. package/docs/en/07-llm-pitfalls.md +0 -724
  118. package/docs/en/08-llm-zero-history-test.md +0 -56
  119. package/docs/en/09-shadow-vs-light-dom.md +0 -174
  120. package/docs/en/11-layouts.md +0 -113
  121. package/docs/en/12-auth-and-api.md +0 -124
  122. package/docs/en/16-bake-cookbook.md +0 -100
  123. package/docs/en/17-shadow-dom-forms.md +0 -192
  124. package/docs/fr/00-the-mado-way.md +0 -85
  125. package/docs/fr/01-routing.md +0 -120
  126. package/docs/fr/02-project-layout.md +0 -84
  127. package/docs/fr/03-static-bake.md +0 -289
  128. package/docs/fr/04-ide-setup.md +0 -162
  129. package/docs/fr/05-why-mado.md +0 -193
  130. package/docs/fr/06-for-backenders.md +0 -438
  131. package/docs/fr/07-llm-pitfalls.md +0 -625
  132. package/docs/fr/08-llm-zero-history-test.md +0 -38
  133. package/docs/fr/09-shadow-vs-light-dom.md +0 -65
  134. package/docs/fr/10-app-architecture.md +0 -138
  135. package/docs/fr/11-layouts.md +0 -47
  136. package/docs/fr/12-auth-and-api.md +0 -76
  137. package/docs/fr/13-deployment.md +0 -57
  138. package/docs/fr/14-testing.md +0 -41
  139. package/docs/fr/15-error-handling.md +0 -50
  140. package/docs/fr/16-bake-cookbook.md +0 -88
  141. package/docs/fr/17-shadow-dom-forms.md +0 -196
  142. package/docs/fr/18-api-freeze-map.md +0 -63
  143. package/docs/fr/19-reactivity-ordering.md +0 -97
  144. package/docs/fr/20-v1-stability.md +0 -88
  145. package/docs/fr/README.md +0 -27
  146. package/docs/ru/00-the-mado-way.md +0 -84
  147. package/docs/ru/01-routing.md +0 -119
  148. package/docs/ru/02-project-layout.md +0 -84
  149. package/docs/ru/03-static-bake.md +0 -250
  150. package/docs/ru/04-ide-setup.md +0 -144
  151. package/docs/ru/05-why-mado.md +0 -193
  152. package/docs/ru/06-for-backenders.md +0 -428
  153. package/docs/ru/07-llm-pitfalls.md +0 -624
  154. package/docs/ru/08-llm-zero-history-test.md +0 -57
  155. package/docs/ru/09-shadow-vs-light-dom.md +0 -63
  156. package/docs/ru/10-app-architecture.md +0 -152
  157. package/docs/ru/11-layouts.md +0 -47
  158. package/docs/ru/12-auth-and-api.md +0 -75
  159. package/docs/ru/13-deployment.md +0 -66
  160. package/docs/ru/14-testing.md +0 -50
  161. package/docs/ru/15-error-handling.md +0 -56
  162. package/docs/ru/16-bake-cookbook.md +0 -95
  163. package/docs/ru/17-shadow-dom-forms.md +0 -193
  164. package/docs/ru/18-api-freeze-map.md +0 -64
  165. package/docs/ru/19-reactivity-ordering.md +0 -95
  166. package/docs/ru/20-v1-stability.md +0 -82
  167. package/docs/ru/README.md +0 -25
  168. package/docs/uk/00-the-mado-way.md +0 -82
  169. package/docs/uk/01-routing.md +0 -76
  170. package/docs/uk/02-project-layout.md +0 -73
  171. package/docs/uk/03-static-bake.md +0 -48
  172. package/docs/uk/04-ide-setup.md +0 -26
  173. package/docs/uk/05-why-mado.md +0 -34
  174. package/docs/uk/06-for-backenders.md +0 -55
  175. package/docs/uk/07-llm-pitfalls.md +0 -145
  176. package/docs/uk/08-llm-zero-history-test.md +0 -34
  177. package/docs/uk/09-shadow-vs-light-dom.md +0 -58
  178. package/docs/uk/10-app-architecture.md +0 -97
  179. package/docs/uk/11-layouts.md +0 -47
  180. package/docs/uk/12-auth-and-api.md +0 -70
  181. package/docs/uk/13-deployment.md +0 -40
  182. package/docs/uk/14-testing.md +0 -34
  183. package/docs/uk/15-error-handling.md +0 -32
  184. package/docs/uk/16-bake-cookbook.md +0 -36
  185. package/docs/uk/17-shadow-dom-forms.md +0 -193
  186. package/docs/uk/18-api-freeze-map.md +0 -61
  187. package/docs/uk/19-reactivity-ordering.md +0 -95
  188. package/docs/uk/20-v1-stability.md +0 -83
  189. package/docs/uk/README.md +0 -27
  190. package/starters/default/src/modules/home/not-found.page.ts +0 -11
  191. /package/docs/en/{15-error-handling.md → 21-error-handling.md} +0 -0
  192. /package/docs/en/{19-reactivity-ordering.md → 31-reactivity-ordering.md} +0 -0
  193. /package/starters/{default → modular}/.editorconfig +0 -0
  194. /package/starters/{default → modular}/eslint.config.mjs +0 -0
  195. /package/starters/{default → modular}/public/favicon.svg +0 -0
  196. /package/starters/{default → modular}/src/modules/auth/_contracts/auth-api.types.ts +0 -0
  197. /package/starters/{default → modular}/src/modules/auth/auth.connector.ts +0 -0
  198. /package/starters/{default → modular}/src/modules/auth/auth.guard.ts +0 -0
  199. /package/starters/{default → modular}/src/modules/auth/auth.public.ts +0 -0
  200. /package/starters/{default → modular}/src/modules/auth/auth.routes.ts +0 -0
  201. /package/starters/{default → modular}/src/modules/auth/auth.service.ts +0 -0
  202. /package/starters/{default → modular}/src/modules/auth/auth.types.ts +0 -0
  203. /package/starters/{default → modular}/src/modules/auth/login.page.ts +0 -0
  204. /package/starters/{default → modular}/src/modules/billing/_contracts/stripe.types.ts +0 -0
  205. /package/starters/{default → modular}/src/modules/billing/api/stripe.connector.ts +0 -0
  206. /package/starters/{default → modular}/src/modules/billing/billing.public.ts +0 -0
  207. /package/starters/{default → modular}/src/modules/billing/billing.routes.ts +0 -0
  208. /package/starters/{default → modular}/src/modules/billing/billing.types.ts +0 -0
  209. /package/starters/{default → modular}/src/modules/billing/components/invoice-status-badge.component.ts +0 -0
  210. /package/starters/{default → modular}/src/modules/billing/data/invoices.resource.ts +0 -0
  211. /package/starters/{default → modular}/src/modules/billing/pages/invoice-detail.page.ts +0 -0
  212. /package/starters/{default → modular}/src/shared/http/http-client.ts +0 -0
  213. /package/starters/{default → modular}/src/shared/http/http-error.ts +0 -0
  214. /package/starters/{default → modular}/src/shared/http/interceptors.ts +0 -0
  215. /package/starters/{default → modular}/src/shared/lib/format-date.ts +0 -0
  216. /package/starters/{default → modular}/src/shared/styles/content.css +0 -0
  217. /package/starters/{default → modular}/src/shared/styles/reset.css +0 -0
  218. /package/starters/{default → modular}/src/shared/styles/shell.css +0 -0
  219. /package/starters/{default → modular}/src/shared/styles/tokens.css +0 -0
  220. /package/starters/{default → modular}/src/shared/ui/x-button.component.ts +0 -0
  221. /package/starters/{default → modular}/src/shared/ui/x-spinner.component.ts +0 -0
@@ -1,32 +1,63 @@
1
- import { resolve } from "node:path";
2
1
  /**
3
2
  * Vite integration for Mado apps.
4
3
  *
5
- * The plugin is intentionally small: Vite owns dev serving, HTML processing,
6
- * assets and bundling; Mado keeps its runtime and static bake semantics.
4
+ * Intentionally minimal: Vite owns dev serving, HTML processing, assets
5
+ * and bundling. This plugin is the bridge that hands the snapshot CLI the
6
+ * three pieces of resolved Vite config it needs and asks Vite for a
7
+ * Mado-flavoured full reload on TypeScript/JavaScript changes.
8
+ *
9
+ * What it owns:
10
+ * 1. a small `build.target` default (matches what the runtime relies on);
11
+ * 2. forcing a full page reload when a `.ts` / `.js` module updates,
12
+ * so signals / components do not have to track HMR state;
13
+ * 3. emitting `_mado/build.json` into the output so
14
+ * `scripts/static.mjs` can read the resolved Vite `base`, `assetsDir`
15
+ * and the user-declared `site` without parsing `vite.config.ts`.
16
+ *
17
+ * What it does NOT own:
18
+ * - HTML ownership (Vite keeps that),
19
+ * - publicDir / outDir / assetsDir defaults (Vite already supplies them),
20
+ * - snapshot orchestration (CLI keeps that),
21
+ * - SSR or hydration.
7
22
  */
8
- export function mado(_options = {}) {
9
- let root = process.cwd();
23
+ export function mado(options = {}) {
24
+ let resolved = null;
10
25
  return {
11
26
  name: "mado",
12
- config(userConfig) {
13
- root = resolve(process.cwd(), userConfig.root ?? ".");
27
+ config() {
14
28
  return {
15
- appType: "spa",
16
- publicDir: "public",
17
- build: {
18
- outDir: "out",
19
- assetsDir: "assets",
20
- target: "es2022",
21
- },
29
+ build: { target: "es2022" },
22
30
  };
23
31
  },
32
+ configResolved(config) {
33
+ resolved = config;
34
+ },
24
35
  handleHotUpdate(ctx) {
25
- if (/\.(ts|js)$/.test(ctx.file)) {
26
- ctx.server.ws.send({ type: "full-reload" });
27
- return [];
36
+ if (!/\.[cm]?[jt]s$/.test(ctx.file))
37
+ return;
38
+ // Invalidate the module graph first; otherwise the reload would
39
+ // serve cached modules and miss the change. Mirrors the canonical
40
+ // Vite "force full reload" recipe.
41
+ const invalidated = new Set();
42
+ for (const mod of ctx.modules) {
43
+ ctx.server.moduleGraph.invalidateModule(mod, invalidated, ctx.timestamp, true);
28
44
  }
29
- return undefined;
45
+ ctx.server.ws.send({ type: "full-reload" });
46
+ return [];
47
+ },
48
+ generateBundle() {
49
+ if (!resolved)
50
+ return;
51
+ this.emitFile({
52
+ type: "asset",
53
+ fileName: "_mado/build.json",
54
+ source: JSON.stringify({
55
+ site: options.site ?? null,
56
+ base: resolved.base,
57
+ assetsDir: resolved.build.assetsDir,
58
+ outDir: resolved.build.outDir,
59
+ }),
60
+ });
30
61
  },
31
62
  };
32
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/vite/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CAAC,WAAkC,EAAE;IACvD,IAAI,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAEzB,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,MAAM,CAAC,UAAU;YACf,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;YAEtD,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,SAAS,EAAE,QAAQ;gBACnB,KAAK,EAAE;oBACL,MAAM,EAAE,KAAK;oBACb,SAAS,EAAE,QAAQ;oBACnB,MAAM,EAAE,QAAQ;iBACjB;aACF,CAAC;QACJ,CAAC;QACD,eAAe,CAAC,GAAG;YACjB,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;gBAC5C,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/vite/index.ts"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,IAAI,CAAC,UAAiC,EAAE;IACtD,IAAI,QAAQ,GAA0B,IAAI,CAAC;IAE3C,OAAO;QACL,IAAI,EAAE,MAAM;QAEZ,MAAM;YACJ,OAAO;gBACL,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;aAC5B,CAAC;QACJ,CAAC;QAED,cAAc,CAAC,MAAM;YACnB,QAAQ,GAAG,MAAM,CAAC;QACpB,CAAC;QAED,eAAe,CAAC,GAAG;YACjB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO;YAC5C,gEAAgE;YAChE,kEAAkE;YAClE,mCAAmC;YACnC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAW,CAAC;YACvC,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC9B,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,gBAAgB,CACrC,GAAG,EACH,WAAyB,EACzB,GAAG,CAAC,SAAS,EACb,IAAI,CACL,CAAC;YACJ,CAAC;YACD,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;YAC5C,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,cAAc;YACZ,IAAI,CAAC,QAAQ;gBAAE,OAAO;YACtB,IAAI,CAAC,QAAQ,CAAC;gBACZ,IAAI,EAAE,OAAO;gBACb,QAAQ,EAAE,kBAAkB;gBAC5B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;oBACrB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI;oBAC1B,IAAI,EAAE,QAAQ,CAAC,IAAI;oBACnB,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS;oBACnC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM;iBAC9B,CAAC;aACH,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
package/docs/README.md CHANGED
@@ -1,12 +1,9 @@
1
1
  # Mado docs
2
2
 
3
- Documentation is organized by language.
3
+ Canonical project documentation is maintained in English only.
4
4
 
5
- | Language | Status |
6
- |---|---|
7
- | [Français](./fr/README.md) | translated |
8
- | [English](./en/README.md) | translated |
9
- | [Ukrainian](./uk/README.md) | translated |
10
- | [Russian](./ru/README.md) | translated |
5
+ - [English documentation](./en/README.md)
11
6
 
12
- Translations and comment localization are tracked separately from core work.
7
+ Older translations (`fr/`, `uk/`, `ru/`) were removed at v0.12. They
8
+ remain available in git history and the `v0.11.1` tag for any
9
+ external links that still need them.
@@ -0,0 +1,132 @@
1
+ # ADR 0001 — Browser-rendered static snapshots
2
+
3
+ **Status:** Accepted (0.12.0)
4
+ **Date:** 2026-06-22
5
+
6
+ ## Context
7
+
8
+ Mado started as a calm browser-native SPA framework for internal tools
9
+ and admin panels. Two new product requirements made that scope too
10
+ narrow:
11
+
12
+ 1. Public-facing surfaces (landing pages, docs sites, product pages)
13
+ need search engines and social preview bots to see a fully rendered
14
+ document on first request, without running JavaScript.
15
+ 2. The same component model that powers the live SPA must produce that
16
+ document — we do not want a second component runtime, a hydration
17
+ protocol, or a server renderer.
18
+
19
+ The conventional answers (Next/Nuxt SSR, Astro, Eleventy, Lit SSR,
20
+ Solid Start, …) each ship at least one of:
21
+
22
+ - a separate component model for the server,
23
+ - a hydration boundary that introduces a second source of truth,
24
+ - a build-time JSX/Vue/Svelte compiler,
25
+ - a Node runtime in production.
26
+
27
+ Mado is positioned as "calm native-first": we cannot adopt any of
28
+ those without breaking the positioning.
29
+
30
+ ## Decision
31
+
32
+ Adopt **browser-rendered static snapshots with Declarative Shadow
33
+ DOM** as the canonical SEO/static path:
34
+
35
+ 1. `mado release` runs `vite build`, then opens each declared static
36
+ route in a real headless Chromium pointed at the build output, and
37
+ serialises the rendered document — including the Shadow DOM as
38
+ Declarative Shadow DOM — into one HTML file per route under
39
+ `out/`.
40
+ 2. The client runtime treats the snapshot as an **atomic takeover**
41
+ target: a Mado component instance reattaches to the existing host
42
+ in place, with no second tree, no hydration, no diff.
43
+ 3. Routes that are not declared `static` stay SPA-only and are served
44
+ through the `_mado/spa.html` fallback the same way they were
45
+ before.
46
+ 4. Vite's `base` is the single source of truth for the public URL
47
+ prefix; the runtime reads it from `import.meta.env.BASE_URL`, the
48
+ CLI reads it from the build bridge (`_mado/build.json`) for
49
+ sitemap / canonical / preview, and the build bridge is dropped
50
+ before the artifact ships.
51
+ 5. Build-time seeds for static routes are strict `JsonValue` only,
52
+ validated by a path-aware walker so a `Date`, `Map`, `undefined`
53
+ field or cycle fails the build instead of silently corrupting the
54
+ first client render.
55
+
56
+ ## Alternatives rejected
57
+
58
+ - **SSR (Next / Nuxt / Solid Start).** Ships a second component model
59
+ and a Node production runtime. Hydration boundary is the largest
60
+ source of recurring bug classes in the ecosystem. Mado's
61
+ positioning rejects both.
62
+
63
+ - **Hydration via an island / partial hydration model (Astro,
64
+ Marko).** Splits the component graph into "static" and "interactive"
65
+ sub-graphs with framework-specific compilers. Adds a second mental
66
+ model for a public-site benefit that DSD already provides.
67
+
68
+ - **Author-time prerendering with `linkedom`/`jsdom`.** Cannot run
69
+ Shadow DOM, adoptedStyleSheets, layout, or any browser API.
70
+ Snapshots would diverge from what the browser actually renders.
71
+
72
+ - **External prerender service (Prerender.io and friends).** Adds an
73
+ external dependency, runs on each request, and Mado has no canonical
74
+ way to detect when to flush its cache.
75
+
76
+ - **Embed a Node runtime that pretends to be a browser.** Same
77
+ divergence problem as `linkedom`, plus a custom DOM polyfill we
78
+ would have to maintain forever.
79
+
80
+ ## Consequences
81
+
82
+ - A compatible Chromium is required at **release time** (not at
83
+ request time, not in production) for projects that declare any
84
+ static route. `mado release` documents how to install one
85
+ (Playwright-managed Chromium, system Chrome, or operator-provided
86
+ path) and CI gates the round-trip with `npx playwright install
87
+ --with-deps chromium` plus `MADO_REQUIRE_BROWSER=1`.
88
+
89
+ - `page.static.paths()` and `page.static.initialData()` must be
90
+ **browser-safe and secret-free**: they execute during the discovery
91
+ pass AND remain in the client bundle. The strict `JsonValue`
92
+ validator catches the common shapes that would otherwise leak.
93
+
94
+ - The framework now has a documented HTTP policy for snapshot capture:
95
+ documents, scripts, stylesheets and tracked resources are fatal;
96
+ favicon-class endpoints are ignored; fonts and paint frames are
97
+ quality hints with bounded timeouts.
98
+
99
+ - The product surface widens from "internal tools / admin panels" to
100
+ "sites and apps". Marketing copy, package metadata, GitHub topics
101
+ and the default starter all change accordingly. The previous
102
+ modular reference architecture is preserved as
103
+ `mado init --starter modular` for long-lived business apps.
104
+
105
+ ## Known limits
106
+
107
+ - Static routes cannot use `Date`, `Map`, `Set`, class instances,
108
+ `undefined` values, cycles, or non-finite numbers in their
109
+ `initialData`. The validator gives a path-aware error.
110
+
111
+ - `mado release` snapshots are deterministic only in a pinned
112
+ environment (same Chromium revision, same source tree). We document
113
+ that determinism contract; reproducing it across CI vendors is the
114
+ operator's responsibility.
115
+
116
+ - Static `paths()` runs at build time. We do not currently support
117
+ incremental re-snapshot from a webhook; a static-content change
118
+ requires a fresh release.
119
+
120
+ - Public client-only state inside a static route (canvas, media
121
+ controllers, transient timers) survives takeover but is not part of
122
+ the snapshot — it materialises only after JS executes.
123
+
124
+ ---
125
+
126
+ ## Original implementation plan (for history)
127
+
128
+ The remainder of this document is the original implementation plan
129
+ that drove the work up to 0.12.0. It is preserved verbatim for
130
+ historical context.
131
+
132
+ ---
@@ -106,7 +106,7 @@ belongs in `*.service.ts`.
106
106
 
107
107
  ### One way to declare routes
108
108
 
109
- See [`01-routing.md`](./01-routing.md).
109
+ See [`12-routing.md`](./12-routing.md).
110
110
 
111
111
  ## What we do NOT do
112
112
 
@@ -0,0 +1,183 @@
1
+ # Quickstart
2
+
3
+ > Goal: have a Mado app running locally, edited from VS Code, and shipped to
4
+ > a static host — in under 10 minutes.
5
+
6
+ ---
7
+
8
+ ## 1. Scaffold
9
+
10
+ Mado 0.12 ships with two starters: the **universal** starter (default) and
11
+ the **modular** reference architecture.
12
+
13
+ ```bash
14
+ # Universal starter (default) — ~15 files, one shared component
15
+ npm exec --package @madojs/mado -- mado init my-app
16
+
17
+ # Modular reference starter — auth shell, guarded zones, billing module
18
+ npm exec --package @madojs/mado -- mado init my-app --starter modular
19
+
20
+ cd my-app
21
+ npm install
22
+ ```
23
+
24
+ What you get either way:
25
+
26
+ - exactly one runtime dependency: `@madojs/mado`;
27
+ - `vite.config.ts` with `mado()` from `@madojs/mado/vite`;
28
+ - `src/main.ts` mounting the router into `#app`;
29
+ - `src/app.routes.ts` (a default export + a named `manifest` export);
30
+ - a `package.json` whose scripts wrap the Mado CLI.
31
+
32
+ ---
33
+
34
+ ## 2. The dev loop
35
+
36
+ ```bash
37
+ npm run dev # Vite dev server, fast HMR for templates/styles
38
+ npm run typecheck # tsc --noEmit
39
+ npm run test # node --test (if your project has tests)
40
+ npm run build # SPA build only (out/ without snapshots)
41
+ npm run release # typecheck + vite build + static snapshots + deploy files
42
+ npm run preview # serve out/ like a real static host
43
+ ```
44
+
45
+ `mado release` is the single command you ship. It produces one folder,
46
+ `out/`, that you can `rsync`/upload to any static host:
47
+
48
+ ```bash
49
+ npm run release
50
+ rsync -avz out/ user@server:/var/www/my-app/
51
+ ```
52
+
53
+ See [20-deployment.md](./20-deployment.md) for nginx / Cloudflare Pages /
54
+ GitHub Pages / S3 recipes.
55
+
56
+ ---
57
+
58
+ ## 3. Your first page
59
+
60
+ Two primitives, that's it (see [10-pages-and-components.md](./10-pages-and-components.md)
61
+ for the full mental model):
62
+
63
+ - **`page()`** — a route. Lives at a URL. Renders in light DOM. Has
64
+ `title` / `head` / `load` / `view` / optional `static`.
65
+ - **`component()`** — a reusable `<x-tag>`. Shadow DOM by default.
66
+
67
+ ```ts
68
+ // src/pages/home.page.ts
69
+ import { html, page } from "@madojs/mado";
70
+
71
+ export default page({
72
+ title: "Home",
73
+ head: () => ({ description: "Hello from Mado" }),
74
+ view: () => html`<h1>Hello, Mado</h1>`,
75
+ });
76
+ ```
77
+
78
+ ```ts
79
+ // src/app.routes.ts
80
+ import { routes } from "@madojs/mado";
81
+
82
+ export const manifest = {
83
+ "/": () => import("./pages/home.page"),
84
+ "*": () => import("./pages/not-found.page"),
85
+ };
86
+
87
+ export default routes(manifest);
88
+ ```
89
+
90
+ Always export both `default` (for the router) and `manifest` (so
91
+ `mado static` can discover bakeable pages).
92
+
93
+ Internal links must be base-aware:
94
+
95
+ ```ts
96
+ import { routeUrl } from "@madojs/mado";
97
+
98
+ html`<a data-link href=${routeUrl("/about")}>About</a>`;
99
+ ```
100
+
101
+ `data-link` lets the router intercept the click — including across
102
+ Shadow DOM. `routeUrl()` resolves against `import.meta.env.BASE_URL`,
103
+ so the same code works whether your app is hosted at `/` or at
104
+ `/docs/`.
105
+
106
+ ---
107
+
108
+ ## 4. IDE setup
109
+
110
+ Out of the box `html` and `css` are tagged-template strings. TypeScript
111
+ and most editors don't highlight them by default. The lit ecosystem's
112
+ tools work because Mado uses the same tag names and binding shapes.
113
+
114
+ ### VS Code (recommended)
115
+
116
+ 1. **Extensions → install [lit-plugin](https://marketplace.visualstudio.com/items?itemName=runem.lit-plugin)** (by `runem`).
117
+ 2. Import `html` / `css` directly — no rename:
118
+
119
+ ```ts
120
+ import { html, css } from "@madojs/mado";
121
+ ```
122
+
123
+ 3. (Optional) Recommended settings for Mado in `.vscode/settings.json`:
124
+
125
+ ```json
126
+ {
127
+ "lit-plugin.rules": {
128
+ "no-unknown-attribute": "off",
129
+ "no-incompatible-type-binding": "off"
130
+ }
131
+ }
132
+ ```
133
+
134
+ `no-incompatible-type-binding: off` is needed because Mado bindings
135
+ accept signals (`Signal<T>`) where the plugin expects raw values.
136
+
137
+ You get: HTML/CSS highlighting inside templates, attribute/event
138
+ auto-complete, go-to-definition for custom elements, typo checking.
139
+
140
+ ### WebStorm / IntelliJ
141
+
142
+ Native support for lit-style template literals since 2021. Nothing to
143
+ install. If highlighting is missing, restart the TS server.
144
+
145
+ ### Neovim / Helix
146
+
147
+ ```bash
148
+ npm install -g lit-html-server
149
+ ```
150
+
151
+ Wire it into your LSP config (`lit_html` in `lspconfig`).
152
+
153
+ ### Optional extras
154
+
155
+ - **Custom Elements Manifest** for auto-complete on your own
156
+ `<x-*>` components: `npx cem analyze --globs "src/**/*.ts"`.
157
+ - **Prettier 3+** formats `html`/`css` template literals via
158
+ `embeddedLanguageFormatting: "auto"` (default).
159
+ - **eslint-plugin-lit** + **eslint-plugin-wc** provide
160
+ template-aware lint rules. Not required.
161
+
162
+ ### What does NOT work today
163
+
164
+ - Type-checking of signal bindings: `<input .value=${count}>` is
165
+ flagged because the plugin expects a string, not a `Signal<number>`.
166
+ Suppress with `// @ts-expect-error` or the settings override above.
167
+ - The `each()` directive is recognised as a plain function — no
168
+ special-case checking inside.
169
+
170
+ Mado works without any IDE plugin — the templates remain valid TS,
171
+ they just won't be syntax-highlighted as HTML.
172
+
173
+ ---
174
+
175
+ ## 5. Where to go next
176
+
177
+ - [10 — Pages and components](./10-pages-and-components.md) — the one rule.
178
+ - [11 — Templates and signals](./11-templates-and-signals.md) — binding shapes.
179
+ - [12 — Routing](./12-routing.md) — manifest, layouts, guards, prefetch.
180
+ - [13 — Data](./13-data.md) — `resource()` / `mutation()` / auth.
181
+ - [14 — Forms](./14-forms.md) — `useForm()` + Shadow DOM input recipes.
182
+ - [15 — Static snapshots](./15-static-snapshots.md) — SEO without SSR.
183
+ - [16 — App architecture](./16-app-architecture.md) — the modular starter, ESLint boundaries.