@madojs/mado 0.11.1 → 0.13.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.
- package/AGENTS.md +116 -32
- package/CHANGELOG.md +216 -1
- package/README.md +158 -173
- package/dist/src/component.d.ts +6 -3
- package/dist/src/component.d.ts.map +1 -0
- package/dist/src/component.js +163 -36
- package/dist/src/component.js.map +1 -1
- package/dist/src/context.d.ts +13 -32
- package/dist/src/context.d.ts.map +1 -0
- package/dist/src/context.js +73 -48
- package/dist/src/context.js.map +1 -1
- package/dist/src/css.d.ts +1 -0
- package/dist/src/css.d.ts.map +1 -0
- package/dist/src/css.js +34 -5
- package/dist/src/css.js.map +1 -1
- package/dist/src/devtools-hook.d.ts +14 -0
- package/dist/src/devtools-hook.d.ts.map +1 -0
- package/dist/src/devtools-hook.js +27 -0
- package/dist/src/devtools-hook.js.map +1 -0
- package/dist/src/devtools.d.ts +24 -22
- package/dist/src/devtools.d.ts.map +1 -0
- package/dist/src/devtools.js +230 -58
- package/dist/src/devtools.js.map +1 -1
- package/dist/src/diagnostics.d.ts +12 -0
- package/dist/src/diagnostics.d.ts.map +1 -0
- package/dist/src/diagnostics.js +68 -8
- package/dist/src/diagnostics.js.map +1 -1
- package/dist/src/each.d.ts +1 -5
- package/dist/src/each.d.ts.map +1 -0
- package/dist/src/each.js +0 -8
- package/dist/src/each.js.map +1 -1
- package/dist/src/forms.d.ts +27 -96
- package/dist/src/forms.d.ts.map +1 -0
- package/dist/src/forms.js +184 -394
- package/dist/src/forms.js.map +1 -1
- package/dist/src/head.d.ts +7 -6
- package/dist/src/head.d.ts.map +1 -0
- package/dist/src/head.js +8 -7
- package/dist/src/head.js.map +1 -1
- package/dist/src/html/bindings.d.ts +1 -0
- package/dist/src/html/bindings.d.ts.map +1 -0
- package/dist/src/html/bindings.js.map +1 -1
- package/dist/src/html/parser.d.ts +4 -5
- package/dist/src/html/parser.d.ts.map +1 -0
- package/dist/src/html/parser.js +64 -15
- package/dist/src/html/parser.js.map +1 -1
- package/dist/src/html/template-types.d.ts +1 -0
- package/dist/src/html/template-types.d.ts.map +1 -0
- package/dist/src/html/template-types.js.map +1 -1
- package/dist/src/html/template.d.ts +5 -1
- package/dist/src/html/template.d.ts.map +1 -0
- package/dist/src/html/template.js +102 -13
- package/dist/src/html/template.js.map +1 -1
- package/dist/src/index.d.ts +15 -12
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +18 -10
- package/dist/src/index.js.map +1 -1
- package/dist/src/json.d.ts +3 -0
- package/dist/src/json.d.ts.map +1 -0
- package/dist/src/json.js +14 -0
- package/dist/src/json.js.map +1 -0
- package/dist/src/lifecycle.d.ts +1 -0
- package/dist/src/lifecycle.d.ts.map +1 -0
- package/dist/src/lifecycle.js +3 -2
- package/dist/src/lifecycle.js.map +1 -1
- package/dist/src/page.d.ts +63 -28
- package/dist/src/page.d.ts.map +1 -0
- package/dist/src/page.js +5 -0
- package/dist/src/page.js.map +1 -1
- package/dist/src/persisted.d.ts +6 -1
- package/dist/src/persisted.d.ts.map +1 -0
- package/dist/src/persisted.js +17 -11
- package/dist/src/persisted.js.map +1 -1
- package/dist/src/resource.d.ts +2 -1
- package/dist/src/resource.d.ts.map +1 -0
- package/dist/src/resource.js +128 -50
- package/dist/src/resource.js.map +1 -1
- package/dist/src/router/base.d.ts +66 -0
- package/dist/src/router/base.d.ts.map +1 -0
- package/dist/src/router/base.js +168 -0
- package/dist/src/router/base.js.map +1 -0
- package/dist/src/router/manifest.d.ts +1 -0
- package/dist/src/router/manifest.d.ts.map +1 -0
- package/dist/src/router/manifest.js +156 -171
- package/dist/src/router/manifest.js.map +1 -1
- package/dist/src/router/match.d.ts +17 -2
- package/dist/src/router/match.d.ts.map +1 -0
- package/dist/src/router/match.js +60 -6
- package/dist/src/router/match.js.map +1 -1
- package/dist/src/router/navigation.d.ts +1 -0
- package/dist/src/router/navigation.d.ts.map +1 -0
- package/dist/src/router/navigation.js +58 -9
- package/dist/src/router/navigation.js.map +1 -1
- package/dist/src/signal.d.ts +1 -0
- package/dist/src/signal.d.ts.map +1 -0
- package/dist/src/signal.js +46 -17
- package/dist/src/signal.js.map +1 -1
- package/dist/src/static-runtime.d.ts +82 -0
- package/dist/src/static-runtime.d.ts.map +1 -0
- package/dist/src/static-runtime.js +209 -0
- package/dist/src/static-runtime.js.map +1 -0
- package/dist/src/vite/index.d.ts +32 -3
- package/dist/src/vite/index.d.ts.map +1 -0
- package/dist/src/vite/index.js +49 -17
- package/dist/src/vite/index.js.map +1 -1
- package/docs/README.md +5 -8
- package/docs/architecture/adr/0001-browser-static-snapshots.md +132 -0
- package/docs/architecture/v1-roadmap.md +19 -0
- package/docs/en/00-the-mado-way.md +1 -1
- package/docs/en/01-quickstart.md +183 -0
- package/docs/en/10-pages-and-components.md +279 -0
- package/docs/en/11-templates-and-signals.md +211 -0
- package/docs/en/12-routing.md +229 -0
- package/docs/en/13-data.md +227 -0
- package/docs/en/14-forms.md +91 -0
- package/docs/en/15-static-snapshots.md +181 -0
- package/docs/en/{10-app-architecture.md → 16-app-architecture.md} +56 -4
- package/docs/en/{13-deployment.md → 20-deployment.md} +79 -17
- package/docs/en/{15-error-handling.md → 21-error-handling.md} +9 -6
- package/docs/en/{14-testing.md → 22-testing.md} +6 -5
- package/docs/en/23-cookbook.md +292 -0
- package/docs/en/24-devtools-and-diagnostics.md +45 -0
- package/docs/en/{18-api-freeze-map.md → 30-api-freeze-map.md} +17 -9
- package/docs/en/{20-v1-stability.md → 32-v1-stability.md} +5 -5
- package/docs/en/33-migration-0.12-0.13.md +56 -0
- package/docs/en/40-llm-guide.md +774 -0
- package/docs/en/{06-for-backenders.md → 41-for-backenders.md} +28 -25
- package/docs/en/{05-why-mado.md → 42-why-mado.md} +3 -3
- package/docs/en/README.md +99 -27
- package/docs/recipes/nginx/Containerfile +26 -0
- package/docs/recipes/nginx/nginx.conf +42 -0
- package/llms.txt +263 -210
- package/package.json +51 -23
- package/scripts/clean.mjs +8 -0
- package/scripts/cli/generate.mjs +57 -10
- package/scripts/cli/help.mjs +13 -5
- package/scripts/cli/index.mjs +31 -7
- package/scripts/cli/init.mjs +19 -19
- package/scripts/cli/release.mjs +38 -83
- package/scripts/cli/run.mjs +5 -3
- package/scripts/logger.mjs +117 -0
- package/scripts/output-guard.mjs +128 -0
- package/scripts/preview.mjs +105 -24
- package/scripts/static/browser.mjs +695 -0
- package/scripts/static/discover.mjs +284 -0
- package/scripts/static/output.mjs +141 -0
- package/scripts/static/serialize.mjs +212 -0
- package/scripts/static/server.mjs +167 -0
- package/scripts/static.mjs +205 -0
- package/starters/default/README.md +57 -55
- package/starters/default/package.json +6 -12
- package/starters/default/src/app.routes.ts +20 -33
- package/starters/default/src/components/feature-card.component.ts +40 -0
- package/starters/default/src/components/live-counter.component.ts +57 -0
- package/starters/default/src/content/guides.ts +55 -0
- package/starters/default/src/main.ts +9 -13
- package/starters/default/src/pages/app.page.ts +41 -0
- package/starters/default/src/pages/guide.page.ts +40 -0
- package/starters/default/src/pages/home.page.ts +49 -0
- package/starters/default/src/pages/not-found.page.ts +18 -0
- package/starters/default/src/styles/document.css +39 -0
- package/starters/default/src/styles/reset.css +37 -0
- package/starters/default/src/styles/tokens.css +30 -0
- package/starters/default/src/styles.d.ts +3 -1
- package/starters/default/src/vite-env.d.ts +1 -1
- package/starters/default/tsconfig.node.json +13 -0
- package/starters/default/vite.config.ts +14 -4
- package/starters/modular/README.md +142 -0
- package/starters/modular/index.html +13 -0
- package/starters/modular/package.json +30 -0
- package/starters/modular/src/app.routes.ts +39 -0
- package/starters/{default → modular}/src/layouts/app-shell.layout.ts +9 -7
- package/starters/{default → modular}/src/layouts/auth-shell.layout.ts +3 -3
- package/starters/modular/src/main.ts +16 -0
- package/starters/{default → modular}/src/modules/auth/login.page.ts +5 -12
- package/starters/{default → modular}/src/modules/billing/pages/invoice-detail.page.ts +3 -4
- package/starters/{default → modular}/src/modules/billing/pages/invoices-list.page.ts +4 -4
- package/starters/{default → modular}/src/modules/home/home.page.ts +5 -7
- package/starters/modular/src/modules/home/not-found.page.ts +14 -0
- package/starters/{default → modular}/src/shared/styles/reset.css +21 -1
- package/starters/modular/src/styles.d.ts +1 -0
- package/starters/modular/src/vite-env.d.ts +1 -0
- package/starters/modular/tsconfig.json +33 -0
- package/starters/modular/tsconfig.node.json +13 -0
- package/starters/modular/vite.config.ts +132 -0
- package/TODO.md +0 -79
- package/dist/src/lazy.d.ts +0 -38
- package/dist/src/lazy.js +0 -73
- package/dist/src/lazy.js.map +0 -1
- package/docs/en/01-routing.md +0 -152
- package/docs/en/02-project-layout.md +0 -124
- package/docs/en/03-static-bake.md +0 -249
- package/docs/en/04-ide-setup.md +0 -162
- package/docs/en/07-llm-pitfalls.md +0 -724
- package/docs/en/08-llm-zero-history-test.md +0 -56
- package/docs/en/09-shadow-vs-light-dom.md +0 -174
- package/docs/en/11-layouts.md +0 -113
- package/docs/en/12-auth-and-api.md +0 -124
- package/docs/en/16-bake-cookbook.md +0 -100
- package/docs/en/17-shadow-dom-forms.md +0 -192
- package/docs/fr/00-the-mado-way.md +0 -85
- package/docs/fr/01-routing.md +0 -120
- package/docs/fr/02-project-layout.md +0 -84
- package/docs/fr/03-static-bake.md +0 -289
- package/docs/fr/04-ide-setup.md +0 -162
- package/docs/fr/05-why-mado.md +0 -193
- package/docs/fr/06-for-backenders.md +0 -438
- package/docs/fr/07-llm-pitfalls.md +0 -625
- package/docs/fr/08-llm-zero-history-test.md +0 -38
- package/docs/fr/09-shadow-vs-light-dom.md +0 -65
- package/docs/fr/10-app-architecture.md +0 -138
- package/docs/fr/11-layouts.md +0 -47
- package/docs/fr/12-auth-and-api.md +0 -76
- package/docs/fr/13-deployment.md +0 -57
- package/docs/fr/14-testing.md +0 -41
- package/docs/fr/15-error-handling.md +0 -50
- package/docs/fr/16-bake-cookbook.md +0 -88
- package/docs/fr/17-shadow-dom-forms.md +0 -196
- package/docs/fr/18-api-freeze-map.md +0 -63
- package/docs/fr/19-reactivity-ordering.md +0 -97
- package/docs/fr/20-v1-stability.md +0 -88
- package/docs/fr/README.md +0 -27
- package/docs/ru/00-the-mado-way.md +0 -84
- package/docs/ru/01-routing.md +0 -119
- package/docs/ru/02-project-layout.md +0 -84
- package/docs/ru/03-static-bake.md +0 -250
- package/docs/ru/04-ide-setup.md +0 -144
- package/docs/ru/05-why-mado.md +0 -193
- package/docs/ru/06-for-backenders.md +0 -428
- package/docs/ru/07-llm-pitfalls.md +0 -624
- package/docs/ru/08-llm-zero-history-test.md +0 -57
- package/docs/ru/09-shadow-vs-light-dom.md +0 -63
- package/docs/ru/10-app-architecture.md +0 -152
- package/docs/ru/11-layouts.md +0 -47
- package/docs/ru/12-auth-and-api.md +0 -75
- package/docs/ru/13-deployment.md +0 -66
- package/docs/ru/14-testing.md +0 -50
- package/docs/ru/15-error-handling.md +0 -56
- package/docs/ru/16-bake-cookbook.md +0 -95
- package/docs/ru/17-shadow-dom-forms.md +0 -193
- package/docs/ru/18-api-freeze-map.md +0 -64
- package/docs/ru/19-reactivity-ordering.md +0 -95
- package/docs/ru/20-v1-stability.md +0 -82
- package/docs/ru/README.md +0 -25
- package/docs/uk/00-the-mado-way.md +0 -82
- package/docs/uk/01-routing.md +0 -76
- package/docs/uk/02-project-layout.md +0 -73
- package/docs/uk/03-static-bake.md +0 -48
- package/docs/uk/04-ide-setup.md +0 -26
- package/docs/uk/05-why-mado.md +0 -34
- package/docs/uk/06-for-backenders.md +0 -55
- package/docs/uk/07-llm-pitfalls.md +0 -145
- package/docs/uk/08-llm-zero-history-test.md +0 -34
- package/docs/uk/09-shadow-vs-light-dom.md +0 -58
- package/docs/uk/10-app-architecture.md +0 -97
- package/docs/uk/11-layouts.md +0 -47
- package/docs/uk/12-auth-and-api.md +0 -70
- package/docs/uk/13-deployment.md +0 -40
- package/docs/uk/14-testing.md +0 -34
- package/docs/uk/15-error-handling.md +0 -32
- package/docs/uk/16-bake-cookbook.md +0 -36
- package/docs/uk/17-shadow-dom-forms.md +0 -193
- package/docs/uk/18-api-freeze-map.md +0 -61
- package/docs/uk/19-reactivity-ordering.md +0 -95
- package/docs/uk/20-v1-stability.md +0 -83
- package/docs/uk/README.md +0 -27
- package/scripts/bake.mjs +0 -570
- package/scripts/package-smoke.mjs +0 -77
- package/scripts/release-notes.mjs +0 -66
- package/scripts/size-budget.mjs +0 -91
- package/starters/default/src/modules/home/not-found.page.ts +0 -11
- package/starters/default/src/shared/ui/x-button.component.ts +0 -49
- /package/docs/en/{19-reactivity-ordering.md → 31-reactivity-ordering.md} +0 -0
- /package/starters/{default → modular}/.editorconfig +0 -0
- /package/starters/{default → modular}/eslint.config.mjs +0 -0
- /package/starters/{default → modular}/public/favicon.svg +0 -0
- /package/starters/{default → modular}/src/modules/auth/_contracts/auth-api.types.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.connector.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.guard.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.public.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.routes.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.service.ts +0 -0
- /package/starters/{default → modular}/src/modules/auth/auth.types.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/_contracts/stripe.types.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/api/stripe.connector.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/billing.public.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/billing.routes.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/billing.types.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/components/invoice-status-badge.component.ts +0 -0
- /package/starters/{default → modular}/src/modules/billing/data/invoices.resource.ts +0 -0
- /package/starters/{default → modular}/src/shared/http/http-client.ts +0 -0
- /package/starters/{default → modular}/src/shared/http/http-error.ts +0 -0
- /package/starters/{default → modular}/src/shared/http/interceptors.ts +0 -0
- /package/starters/{default → modular}/src/shared/lib/format-date.ts +0 -0
- /package/starters/{default → modular}/src/shared/styles/content.css +0 -0
- /package/starters/{default → modular}/src/shared/styles/shell.css +0 -0
- /package/starters/{default → modular}/src/shared/styles/tokens.css +0 -0
- /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
|
-
>
|
|
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
|
|
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 development release: **0.13.0**.
|
|
11
14
|
- Built on Web Components + signals + tagged-template `html`.
|
|
12
|
-
-
|
|
13
|
-
|
|
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
|
|
@@ -295,8 +301,9 @@ const { register, handleSubmit } = useForm({ resolver: yupResolver(schema) });
|
|
|
295
301
|
import { useForm } from "@madojs/mado";
|
|
296
302
|
|
|
297
303
|
const f = useForm({
|
|
298
|
-
|
|
299
|
-
|
|
304
|
+
initial: { email: "", age: "" as number | "" },
|
|
305
|
+
validate: async (values, { signal }) =>
|
|
306
|
+
await api.valid(values, { signal }) ? null : { email: "Unavailable" },
|
|
300
307
|
});
|
|
301
308
|
|
|
302
309
|
html`
|
|
@@ -305,7 +312,8 @@ html`
|
|
|
305
312
|
await api.save(v);
|
|
306
313
|
})}
|
|
307
314
|
>
|
|
308
|
-
<input name="email" @input=${f.onInput} @blur=${f.onBlur} />
|
|
315
|
+
<input name="email" type="email" required @input=${f.onInput} @blur=${f.onBlur} />
|
|
316
|
+
<input name="age" type="number" min="18" @input=${f.onInput} />
|
|
309
317
|
${() =>
|
|
310
318
|
f.touched().email && f.errors().email
|
|
311
319
|
? html`<small>${f.errors().email}</small>`
|
|
@@ -315,7 +323,8 @@ html`
|
|
|
315
323
|
`;
|
|
316
324
|
```
|
|
317
325
|
|
|
318
|
-
|
|
326
|
+
HTML owns native constraints. Custom validation receives an `AbortSignal`.
|
|
327
|
+
Use `setField`, not a schema/field-array abstraction.
|
|
319
328
|
|
|
320
329
|
### 11. Styles — `css\`\`` + Shadow DOM by default
|
|
321
330
|
|
|
@@ -362,6 +371,10 @@ component("x-child", ({ host }) => {
|
|
|
362
371
|
});
|
|
363
372
|
```
|
|
364
373
|
|
|
374
|
+
This interoperates through the Web Components `context-request` protocol.
|
|
375
|
+
Providers may expose function values; only real Mado Signals are treated as
|
|
376
|
+
reactive sources. Subscriptions are removed with the active lifecycle.
|
|
377
|
+
|
|
365
378
|
### 13. Component registration imports
|
|
366
379
|
|
|
367
380
|
Custom elements are global after registration, but the browser never imports a
|
|
@@ -384,16 +397,54 @@ Rules:
|
|
|
384
397
|
- Tiny leaf components used everywhere → importing in `main.ts` is acceptable.
|
|
385
398
|
- Do **not** bulk-import every component "just in case".
|
|
386
399
|
|
|
387
|
-
### 14.
|
|
400
|
+
### 14. Static snapshots — browser-rendered, not SSR/SSG
|
|
401
|
+
|
|
402
|
+
`mado static` (normally invoked through `mado release`) captures real
|
|
403
|
+
HTML by navigating each page in a headless Chromium and serialising
|
|
404
|
+
the resulting DOM, including the Shadow DOM through Declarative Shadow
|
|
405
|
+
DOM (DSD). On first paint the live SPA **atomically replaces** the
|
|
406
|
+
static tree — there is no hydration protocol, no node reconciliation
|
|
407
|
+
and no per-attribute diffing.
|
|
408
|
+
|
|
409
|
+
A page opts in by declaring `static` on `page({ ... })`:
|
|
410
|
+
|
|
411
|
+
```ts
|
|
412
|
+
// Static landing page
|
|
413
|
+
export default page({
|
|
414
|
+
static: true,
|
|
415
|
+
title: "Home",
|
|
416
|
+
head: () => ({ description: "Public landing" }),
|
|
417
|
+
view: () => html`<main><h1>Hello</h1></main>`,
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
// Dynamic static route
|
|
421
|
+
export default page({
|
|
422
|
+
static: {
|
|
423
|
+
paths: async () => [{ slug: "alpha" }, { slug: "beta" }],
|
|
424
|
+
initialData: async ({ slug }) => loadGuide(slug),
|
|
425
|
+
},
|
|
426
|
+
title: ({ slug }) => `Guide: ${slug}`,
|
|
427
|
+
view: (ctx) => html`<article>${ctx.data}</article>`,
|
|
428
|
+
});
|
|
429
|
+
```
|
|
388
430
|
|
|
389
|
-
|
|
390
|
-
not SSR with hydration and not a Next-style SSG runtime.
|
|
431
|
+
Important constraints:
|
|
391
432
|
|
|
392
|
-
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
433
|
+
- Static pages cannot use guards (route- or layout-level) — they are
|
|
434
|
+
public by definition.
|
|
435
|
+
- `paths()` and `initialData()` run at discovery AND ship in the
|
|
436
|
+
client bundle. Keep them browser-safe; never read secrets.
|
|
437
|
+
- Wildcard routes (`*`) cannot be static.
|
|
438
|
+
- The `static` discovery uses Vite SSR as a control plane only;
|
|
439
|
+
nothing is rendered in Node. The actual capture happens in
|
|
440
|
+
headless Chromium.
|
|
441
|
+
|
|
442
|
+
<!-- docs-lint:allow-legacy-mention -->
|
|
443
|
+
There is no `bake`, no `bake.paths`, no `bake.data`, no
|
|
444
|
+
`bake.revalidate`, no `npm run bake`, no `linkedom` renderer, no
|
|
445
|
+
"meta-shell". Those names refer to a removed system; do not generate
|
|
446
|
+
them. If you see them in older docs, treat them as obsolete.
|
|
447
|
+
<!-- /docs-lint:allow-legacy-mention -->
|
|
397
448
|
|
|
398
449
|
## SOFT GUIDELINES — recommended, but not critical
|
|
399
450
|
|
|
@@ -409,19 +460,52 @@ not SSR with hydration and not a Next-style SSG runtime.
|
|
|
409
460
|
|
|
410
461
|
## Project structure
|
|
411
462
|
|
|
463
|
+
Two official starters target the same Mado runtime:
|
|
464
|
+
|
|
412
465
|
```
|
|
466
|
+
# universal starter (default — `mado init my-app`)
|
|
467
|
+
src/
|
|
468
|
+
├── main.ts
|
|
469
|
+
├── app.routes.ts
|
|
470
|
+
├── pages/ ← one *.page.ts per route, light DOM
|
|
471
|
+
├── components/ ← reusable Web Components (Shadow DOM)
|
|
472
|
+
├── content/ ← static content (guides, etc.)
|
|
473
|
+
└── styles/
|
|
474
|
+
|
|
475
|
+
# modular starter (`mado init my-app --starter modular`)
|
|
413
476
|
src/
|
|
414
|
-
├── main.ts
|
|
415
|
-
├── app.routes.ts
|
|
416
|
-
├── layouts/
|
|
417
|
-
├── shared/
|
|
418
|
-
└── modules/
|
|
477
|
+
├── main.ts
|
|
478
|
+
├── app.routes.ts
|
|
479
|
+
├── layouts/ ← stateless app-zone shells (`page({ child })`)
|
|
480
|
+
├── shared/ ← ui, http, lib, styles
|
|
481
|
+
└── modules/ ← bounded contexts with pages/data/api/services
|
|
419
482
|
```
|
|
420
483
|
|
|
484
|
+
The modular starter ships a dev-only mock API in `vite.config.ts`
|
|
485
|
+
(`/api/auth/*`, `/api/billing/*`). Disable with `MADO_MOCK_API=0`
|
|
486
|
+
or remove the `devApiMock()` plugin before pointing at a real backend.
|
|
487
|
+
|
|
488
|
+
## Internal links — always `routeUrl()`
|
|
489
|
+
|
|
490
|
+
Vite's `base` flows automatically into `appBase` and `routeUrl()`. App
|
|
491
|
+
code MUST use `routeUrl()` for every internal anchor so the URL stays
|
|
492
|
+
correct under `/`, `/mado/` or any sub-path deployment, and MUST opt
|
|
493
|
+
in with `data-link` for SPA navigation:
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
import { routeUrl } from "@madojs/mado";
|
|
497
|
+
|
|
498
|
+
html`<a data-link href=${routeUrl("/users/42")}>User</a>`;
|
|
499
|
+
html`<a data-link href=${routeUrl("/")}>Home</a>`; // → "/mado/" under base
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
`navigate("/users/42")` for programmatic navigation. Both accept route
|
|
503
|
+
paths (no base) and apply the active base internally.
|
|
504
|
+
|
|
421
505
|
## App architecture for LLM
|
|
422
506
|
|
|
423
507
|
When generating an app, prefer the blessed production shape from
|
|
424
|
-
`docs/en/
|
|
508
|
+
`docs/en/16-app-architecture.md` and the `starters/default/` example:
|
|
425
509
|
|
|
426
510
|
- `src/main.ts` mounts `routesApi.view` and imports only global styles,
|
|
427
511
|
providers, and tiny shared components.
|
|
@@ -440,18 +524,18 @@ When generating an app, prefer the blessed production shape from
|
|
|
440
524
|
|
|
441
525
|
| Question | File |
|
|
442
526
|
| -------------------------------- | -------------------------------- |
|
|
443
|
-
| How does reactivity work? | `src/signal.ts`
|
|
527
|
+
| How does reactivity work? | `src/signal.ts` |
|
|
444
528
|
| How are templates parsed? | `src/html/` |
|
|
445
529
|
| How does the router work? | `src/router/` |
|
|
446
|
-
| How does resource + cache work? | `src/resource.ts`
|
|
447
|
-
| How do forms work? | `src/forms.ts`
|
|
448
|
-
| How should an app be structured? | `docs/en/
|
|
449
|
-
| How should errors be handled? | `docs/en/
|
|
450
|
-
| How should
|
|
451
|
-
| What API is stable? | `docs/en/
|
|
452
|
-
| What ordering is guaranteed? | `docs/en/
|
|
453
|
-
| What does v1 stability mean? | `docs/en/
|
|
454
|
-
| When something goes wrong | `docs/en/
|
|
530
|
+
| How does resource + cache work? | `src/resource.ts` |
|
|
531
|
+
| How do forms work? | `src/forms.ts` |
|
|
532
|
+
| How should an app be structured? | `docs/en/16-app-architecture.md` |
|
|
533
|
+
| How should errors be handled? | `docs/en/21-error-handling.md` |
|
|
534
|
+
| How should static snapshots be used? | `docs/en/15-static-snapshots.md` / `docs/en/23-cookbook.md` |
|
|
535
|
+
| What API is stable? | `docs/en/30-api-freeze-map.md` |
|
|
536
|
+
| What ordering is guaranteed? | `docs/en/31-reactivity-ordering.md` |
|
|
537
|
+
| What does v1 stability mean? | `docs/en/32-v1-stability.md` |
|
|
538
|
+
| When something goes wrong | `docs/en/40-llm-guide.md` |
|
|
455
539
|
|
|
456
540
|
## Before committing
|
|
457
541
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,221 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.13.0 - 2026-07-11
|
|
4
|
+
|
|
5
|
+
The final planned pre-v1 breaking release hardens ownership and freezes the
|
|
6
|
+
small platform-first API.
|
|
7
|
+
|
|
8
|
+
### Breaking
|
|
9
|
+
|
|
10
|
+
- Forms now use `useForm({ initial, validate? })`; native controls and
|
|
11
|
+
`ValidityState` own constraints. The schema and field-array APIs are removed.
|
|
12
|
+
- The root surface drops `lazy`, `list` and accidental low-level exports. The
|
|
13
|
+
only public subpaths are the package root, `/vite` and `/devtools.js`.
|
|
14
|
+
- `page.load` is synchronous and returns a value or `Resource`; Promises are
|
|
15
|
+
rejected with a targeted diagnostic.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- `render()` returns a disposer and public `unmount(container)` releases owned
|
|
20
|
+
bindings, events, effects and nested templates.
|
|
21
|
+
- Structured browser and CLI diagnostics, including JSON CLI output, log-level
|
|
22
|
+
controls and `NO_COLOR` support.
|
|
23
|
+
- A development-only Shadow DOM devtools overlay with reactivity, component,
|
|
24
|
+
router/data and timeline/error views, plus an exported controller.
|
|
25
|
+
- The Web Components `context-request` protocol with subscriptions and
|
|
26
|
+
lifecycle cleanup.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Destructive output paths are realpath-checked and cleaned only when owned by
|
|
31
|
+
a `.mado-output` sentinel.
|
|
32
|
+
- JSON-LD/static seed serialization escapes script-breaking input.
|
|
33
|
+
- Effect, component, render and navigation teardown is transactional and
|
|
34
|
+
idempotent, including initial failures and same-tick DOM moves.
|
|
35
|
+
- Route literals are escaped, template markers are opaque and deterministic,
|
|
36
|
+
unsupported self-closing/template-child shapes fail early.
|
|
37
|
+
- Resource cache identity includes the fetcher; `staleTime: 0`, expiry,
|
|
38
|
+
invalidation, refresh and concurrent mutation generations have defined
|
|
39
|
+
semantics. Persisted signal disposal no longer deletes storage implicitly.
|
|
40
|
+
- Static capture blocks undeclared external requests, preserves form/focus
|
|
41
|
+
takeover state, runs bounded route capture and emits portable build metadata.
|
|
42
|
+
- `mado build` and published route discovery now feed the standalone static
|
|
43
|
+
pipeline correctly.
|
|
44
|
+
|
|
45
|
+
### Tooling and release
|
|
46
|
+
|
|
47
|
+
- Framework/default starter use TypeScript 7; the ESLint modular starter stays
|
|
48
|
+
on TypeScript 6. Node 22.12+ and Vite 8 are the supported baseline.
|
|
49
|
+
- Lightning CSS was removed from starters in favour of Vite's standard CSS
|
|
50
|
+
pipeline.
|
|
51
|
+
- Reproducible tarballs, inline source maps, API golden files, compiled docs
|
|
52
|
+
snippets and a single `verify:release` gate were added.
|
|
53
|
+
- CI covers Node 22/24, Chromium/Firefox/WebKit modular flows and Windows
|
|
54
|
+
package smoke. Runtime and devtools bundles have separate size budgets.
|
|
55
|
+
- Windows package smoke invokes `npm-cli.js` through the active `node.exe`
|
|
56
|
+
instead of relying on `npm`/`npx` command shims, and launches preview
|
|
57
|
+
directly so CI does not leak a nested process tree.
|
|
58
|
+
|
|
59
|
+
See [the migration guide](./docs/en/33-migration-0.12-0.13.md).
|
|
60
|
+
|
|
61
|
+
## 0.12.0 - 2026-06-24
|
|
62
|
+
|
|
63
|
+
### Stable polish
|
|
64
|
+
|
|
65
|
+
Two rounds of post-rc polish for the 0.12.0 cut:
|
|
66
|
+
|
|
67
|
+
#### Pre-merge fixes (carried over from the rc.1 review)
|
|
68
|
+
|
|
69
|
+
- **Router base/prefetch.** `routeUrl()` on `"/"` and hover-prefetch
|
|
70
|
+
on Vite `base` deployments now resolve correctly under any sub-path
|
|
71
|
+
(`/`, `/mado/`, `/admin/`).
|
|
72
|
+
- **`mado static` cleanup.** No more race between `process.exit` and
|
|
73
|
+
capture; canonical `<link>` is stripped on SPA navigation into pages
|
|
74
|
+
that don't declare their own head metadata.
|
|
75
|
+
- **Discovery.** `mado static` no longer bypasses `fatal()` when
|
|
76
|
+
Vite SSR import fails; failures abort the snapshot.
|
|
77
|
+
- **Modular starter.** All internal anchors flow through
|
|
78
|
+
`routeUrl()` + `data-link`; generators are context-aware and
|
|
79
|
+
refuse to overwrite existing files.
|
|
80
|
+
- **`package:smoke`.** Now exercises both the default and modular
|
|
81
|
+
starters end to end.
|
|
82
|
+
- **Release publishing.** `next` versions stay on the `next`
|
|
83
|
+
dist-tag; `latest` is reserved for stable cuts. The release and
|
|
84
|
+
weekly workflows install a pinned Playwright Chromium so static
|
|
85
|
+
snapshots never silently skip on CI.
|
|
86
|
+
- **`mado preview`.** Prints the active base URL so users browsing
|
|
87
|
+
under a sub-path see the right entrypoint.
|
|
88
|
+
- **`TODO.md` / `CONTRIBUTING.md` / `package.json#files`** trimmed
|
|
89
|
+
to match the post-rc reality.
|
|
90
|
+
|
|
91
|
+
#### Documentation reorganisation
|
|
92
|
+
|
|
93
|
+
`docs/en/` was rewritten so users (and LLMs) get one happy path:
|
|
94
|
+
**"don't think `shadow: true` vs `shadow: false`; pick `page()` for
|
|
95
|
+
URLs and `component()` for reusable widgets."**
|
|
96
|
+
|
|
97
|
+
- **New flagship doc** `docs/en/10-pages-and-components.md` —
|
|
98
|
+
"the one rule": `page()` for routes, `component()` for reusable
|
|
99
|
+
`<x-tag>`s. Anti-patterns + decision table + `{ shadow: false }`
|
|
100
|
+
escape hatch.
|
|
101
|
+
- **New numbering** groups docs into Start here / Concepts /
|
|
102
|
+
Production / Reference / Meta. Migration map for stale links is in
|
|
103
|
+
`docs/en/README.md`.
|
|
104
|
+
- **Consolidated pages** —
|
|
105
|
+
`11-templates-and-signals.md` (NEW), `12-routing.md` (merges old
|
|
106
|
+
routing + layouts), `13-data.md` (merges old data + auth/api),
|
|
107
|
+
`14-forms.md` (merges old forms + Shadow-DOM forms),
|
|
108
|
+
`15-static-snapshots.md`, `16-app-architecture.md` (merges old
|
|
109
|
+
project-layout), `01-quickstart.md` (merges old IDE-setup),
|
|
110
|
+
`40-llm-guide.md` (merges old pitfalls + zero-history test).
|
|
111
|
+
- **Deleted** `docs/fr`, `docs/uk`, `docs/ru` — English-only since
|
|
112
|
+
v0.12. Several legacy `docs/en/*` files were removed; their
|
|
113
|
+
content lives in the consolidated pages.
|
|
114
|
+
- **Truth pass on retained prose.** Killed obsolete claims:
|
|
115
|
+
no more "tsc-only", "no bundler", "SSE reload", "tsc → browser",
|
|
116
|
+
"edge prerender", "import maps". Vite is consistently named as
|
|
117
|
+
the canonical transport.
|
|
118
|
+
- **`scripts/docs-lint.mjs`** now also blocks the obsolete vocabulary
|
|
119
|
+
above and any links to renamed `docs/en/*` filenames in active
|
|
120
|
+
docs; the migration table in `docs/en/README.md` is wrapped in a
|
|
121
|
+
`docs-lint:allow-legacy-mention` block.
|
|
122
|
+
|
|
123
|
+
## 0.12.0-rc.1 - 2026-06-22
|
|
124
|
+
|
|
125
|
+
The unified pre-merge release. Mado is no longer "a calm browser-native
|
|
126
|
+
SPA framework for internal tools"; it becomes **"a calm native-first
|
|
127
|
+
web framework for sites and apps"** with one component model end to end.
|
|
128
|
+
The full plan is preserved as
|
|
129
|
+
[ADR 0001 — Browser-rendered static snapshots](./docs/architecture/adr/0001-browser-static-snapshots.md).
|
|
130
|
+
|
|
131
|
+
### Positioning
|
|
132
|
+
|
|
133
|
+
- New tagline: **One component model. One page model. One release command.**
|
|
134
|
+
- README, `package.json` (description + keywords), CLI help and starter
|
|
135
|
+
READMEs all updated to the sites-and-apps positioning.
|
|
136
|
+
- `MADO_UNIFIED_PRE_MERGE_PLAN.MD` moved to
|
|
137
|
+
`docs/architecture/adr/0001-browser-static-snapshots.md`.
|
|
138
|
+
|
|
139
|
+
### Added
|
|
140
|
+
|
|
141
|
+
- **`src/router/base.ts`** — single source of truth for the Vite base.
|
|
142
|
+
Exports `appBase`, `normalizeBase`, `stripBase`, `withBase` and the
|
|
143
|
+
new public `routeUrl()` helper. The runtime reads
|
|
144
|
+
`import.meta.env.BASE_URL` once and exposes it through these helpers
|
|
145
|
+
so every internal link is base-aware without any application
|
|
146
|
+
configuration.
|
|
147
|
+
- **Production-served snapshot → live takeover E2E gate.**
|
|
148
|
+
`test/static/dsd-takeover.test.mjs` now scaffolds a real app, runs
|
|
149
|
+
`mado release`, hosts it through `mado preview` and asserts the
|
|
150
|
+
takeover contract through headless Chromium with strict
|
|
151
|
+
no-`.catch()` assertions.
|
|
152
|
+
- **Base-path fixture.** `test/static/base-path.test.mjs` proves the
|
|
153
|
+
whole `/mado/` deployment shape end to end: build, sitemap, capture,
|
|
154
|
+
preview redirects, SPA fallback, runtime stripBase/withBase.
|
|
155
|
+
- **Canonical / `og:url` auto-fallback.** When a page does not declare
|
|
156
|
+
either, the snapshot pipeline derives an absolute
|
|
157
|
+
`site + base + pathname` URL, deduplicates duplicates and rejects
|
|
158
|
+
localhost / capture-origin values.
|
|
159
|
+
- **Strict `JsonValue` validator** with path-aware errors. Date / Map /
|
|
160
|
+
Set / class instances / undefined / NaN / Infinity / cycles all fail
|
|
161
|
+
the build with the exact JSON path that broke
|
|
162
|
+
(`[mado:static] /products/keyboard: seed.product.createdAt is Date`).
|
|
163
|
+
- **Universal default starter** (`mado init my-app`). ~15 source
|
|
164
|
+
files, no backend required, demonstrates one Shadow Component shared
|
|
165
|
+
between a static landing page and a live SPA route.
|
|
166
|
+
- **Modular starter preserved** (`mado init my-app --starter modular`)
|
|
167
|
+
as the long-lived business-application reference architecture.
|
|
168
|
+
- **HTTP policy documented** in `scripts/static/browser.mjs`: fatal
|
|
169
|
+
vs ignored vs quality-hint classes are explicit, with bounded
|
|
170
|
+
timeouts for fonts and paint frames.
|
|
171
|
+
- **`scripts/docs-lint.mjs`** refuses the old vocabulary in current
|
|
172
|
+
docs (page.bake, mado bake, out/baked, "No Vite required",
|
|
173
|
+
"internal tools only") while still allowing it in migration guides
|
|
174
|
+
and ADRs.
|
|
175
|
+
- **Required CI gate** `.github/workflows/ci.yml → static-snapshot`
|
|
176
|
+
installs Playwright-managed Chromium with
|
|
177
|
+
`npx playwright install --with-deps chromium` and runs the static
|
|
178
|
+
tests under `MADO_REQUIRE_BROWSER=1` so they cannot silently skip.
|
|
179
|
+
|
|
180
|
+
### Changed (breaking)
|
|
181
|
+
|
|
182
|
+
- **`mado build`** in app contexts now performs a Vite production
|
|
183
|
+
build of the deployable SPA (`vite build`). Inside the framework
|
|
184
|
+
repository it still calls `tsc`. The internal tsc compile is
|
|
185
|
+
exposed via `npm run build` in the repo. Use `mado typecheck` if
|
|
186
|
+
you only wanted `tsc --noEmit`.
|
|
187
|
+
- **`out/_mado/build.json`** is dropped from the final release
|
|
188
|
+
artifact. It is internal CLI plumbing emitted by the
|
|
189
|
+
`@madojs/mado/vite` plugin so `mado static` and `mado preview` can
|
|
190
|
+
read the resolved Vite base/site without parsing `vite.config.ts`.
|
|
191
|
+
`mado preview` now derives the base from the build bridge OR from
|
|
192
|
+
the asset prefix in `out/index.html`, so the preview works on the
|
|
193
|
+
shipped artifact.
|
|
194
|
+
- **Static output staging.** `out/_mado/spa.html` is no longer touched
|
|
195
|
+
until every static route captures cleanly; a failure mid-pipeline
|
|
196
|
+
leaves the previous deployment intact. `cleanupTemp()` always runs
|
|
197
|
+
in `finally`.
|
|
198
|
+
- **`whenStable()` phase-bounded.** The runtime now waits for
|
|
199
|
+
routeReady (cap: 15s) and tracked resources (cap: 15s) separately
|
|
200
|
+
so timeout diagnostics name the failing phase. Fonts and paint
|
|
201
|
+
frames are best-effort with bounded timeouts (5s / 1s); on timeout
|
|
202
|
+
the snapshot proceeds with a diagnostic instead of failing.
|
|
203
|
+
- **Browser launch order.** `chromium.launch()` (Playwright-managed)
|
|
204
|
+
is tried *before* `channel: "chrome"` so CI determinism does not
|
|
205
|
+
depend on whatever branded Chrome happens to be installed.
|
|
206
|
+
|
|
207
|
+
### Migration
|
|
208
|
+
|
|
209
|
+
| Before | After |
|
|
210
|
+
|---|---|
|
|
211
|
+
| `page.bake` | `page.static` |
|
|
212
|
+
| `mado bake` | `mado static` |
|
|
213
|
+
| `out/baked/...` | `out/<route>/index.html` |
|
|
214
|
+
| `#bake` data | `data-mado-static-data` script |
|
|
215
|
+
| `shadow: false` for SEO | open Shadow DOM (snapshotted as DSD) |
|
|
216
|
+
| `site` was optional | required for any `static` route |
|
|
217
|
+
| Vite plugin optional | canonical transport |
|
|
218
|
+
| `mado build` ≈ `tsc` | `mado build` ≈ `vite build` |
|
|
4
219
|
|
|
5
220
|
## 0.11.1 - 2026-06-21
|
|
6
221
|
|