@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
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# Static snapshots cookbook
|
|
2
|
+
|
|
3
|
+
> Concrete recipes for `mado static`. Concept and API in
|
|
4
|
+
> [15-static-snapshots.md](./15-static-snapshots.md); failure modes and CI
|
|
5
|
+
> guidance at the end of this file.
|
|
6
|
+
|
|
7
|
+
Every recipe assumes:
|
|
8
|
+
|
|
9
|
+
- Vite is the build transport (`@madojs/mado/vite` plugin).
|
|
10
|
+
- A public origin is configured (`mado({ site })` or
|
|
11
|
+
`MADO_SITE=https://your.site mado release`).
|
|
12
|
+
- `mado release` is the release command (it runs `vite build` →
|
|
13
|
+
`mado static` → writes deployment files into `out/`).
|
|
14
|
+
|
|
15
|
+
## 1. Single static landing page
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// src/pages/home.page.ts
|
|
19
|
+
import { html, page } from "@madojs/mado";
|
|
20
|
+
|
|
21
|
+
export default page({
|
|
22
|
+
static: true,
|
|
23
|
+
title: "Home",
|
|
24
|
+
head: () => ({
|
|
25
|
+
description: "Welcome to the Mado App.",
|
|
26
|
+
}),
|
|
27
|
+
view: () => html`
|
|
28
|
+
<main>
|
|
29
|
+
<h1>Mado App</h1>
|
|
30
|
+
<p>One component model. One page model. One release command.</p>
|
|
31
|
+
</main>
|
|
32
|
+
`,
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
After `mado release`:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
out/
|
|
40
|
+
index.html ← captured snapshot
|
|
41
|
+
assets/...
|
|
42
|
+
_mado/spa.html ← SPA fallback for other routes
|
|
43
|
+
sitemap.xml
|
|
44
|
+
_headers / _redirects
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 2. Blog with file-system content
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
// src/content/posts.ts
|
|
51
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
52
|
+
import { resolve } from "node:path";
|
|
53
|
+
|
|
54
|
+
export interface Post {
|
|
55
|
+
slug: string;
|
|
56
|
+
title: string;
|
|
57
|
+
date: string;
|
|
58
|
+
html: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const dir = resolve(process.cwd(), "content/posts");
|
|
62
|
+
|
|
63
|
+
export function listPosts(): Post[] {
|
|
64
|
+
return readdirSync(dir)
|
|
65
|
+
.filter((f) => f.endsWith(".md"))
|
|
66
|
+
.map((file) => loadPost(file));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function loadPost(file: string): Post {
|
|
70
|
+
// Replace with your real Markdown pipeline.
|
|
71
|
+
return JSON.parse(readFileSync(resolve(dir, file), "utf8"));
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
// src/pages/post.page.ts
|
|
77
|
+
import { html, page } from "@madojs/mado";
|
|
78
|
+
import { listPosts, loadPost, type Post } from "../content/posts";
|
|
79
|
+
|
|
80
|
+
export default page<{ slug: string }, Post>({
|
|
81
|
+
static: {
|
|
82
|
+
paths: async () =>
|
|
83
|
+
listPosts().map((p) => ({ slug: p.slug })),
|
|
84
|
+
initialData: async ({ slug }) =>
|
|
85
|
+
loadPost(`${slug}.json`),
|
|
86
|
+
},
|
|
87
|
+
title: (_, seed) => seed?.title ?? "Post",
|
|
88
|
+
head: (_, seed) => ({
|
|
89
|
+
description: seed?.title,
|
|
90
|
+
}),
|
|
91
|
+
view: (ctx) => html`
|
|
92
|
+
<article>
|
|
93
|
+
<h1>${ctx.data.title}</h1>
|
|
94
|
+
<time>${ctx.data.date}</time>
|
|
95
|
+
${html([ctx.data.html] as unknown as TemplateStringsArray)}
|
|
96
|
+
</article>
|
|
97
|
+
`,
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Output: one `out/posts/<slug>/index.html` per post, each carrying its
|
|
102
|
+
own canonical and `og:url`.
|
|
103
|
+
|
|
104
|
+
> File-system reads happen during *discovery* (Node side). They never
|
|
105
|
+
> ship in the client bundle. The captured *initial data* does ship —
|
|
106
|
+
> keep it free of secrets.
|
|
107
|
+
|
|
108
|
+
## 3. Product catalogue from JSON
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { html, page } from "@madojs/mado";
|
|
112
|
+
import products from "../content/products.json" with { type: "json" };
|
|
113
|
+
|
|
114
|
+
interface Product {
|
|
115
|
+
slug: string;
|
|
116
|
+
name: string;
|
|
117
|
+
price: number;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export default page<{ slug: string }, Product>({
|
|
121
|
+
static: {
|
|
122
|
+
paths: async () => products.map((p) => ({ slug: p.slug })),
|
|
123
|
+
initialData: async ({ slug }) =>
|
|
124
|
+
products.find((p) => p.slug === slug)!,
|
|
125
|
+
},
|
|
126
|
+
title: (_, seed) => seed?.name ?? "Product",
|
|
127
|
+
view: (ctx) => html`
|
|
128
|
+
<main>
|
|
129
|
+
<h1>${ctx.data.name}</h1>
|
|
130
|
+
<p>$${ctx.data.price.toFixed(2)}</p>
|
|
131
|
+
</main>
|
|
132
|
+
`,
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## 4. Documentation site
|
|
137
|
+
|
|
138
|
+
A docs site is typically:
|
|
139
|
+
|
|
140
|
+
- Many static guides keyed by `slug`.
|
|
141
|
+
- A few hand-written landing pages.
|
|
142
|
+
- One SPA route for the search modal (kept dynamic).
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
// src/app.routes.ts
|
|
146
|
+
import { routes } from "@madojs/mado";
|
|
147
|
+
import home from "./pages/home.page";
|
|
148
|
+
import guide from "./pages/guide.page";
|
|
149
|
+
import search from "./pages/search.page";
|
|
150
|
+
|
|
151
|
+
export const manifest = {
|
|
152
|
+
"/": home, // static
|
|
153
|
+
"/guides/:slug": guide, // dynamic static
|
|
154
|
+
"/search": search, // SPA-only (no `static` field)
|
|
155
|
+
"*": () => import("./pages/not-found.page"),
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export default routes(manifest);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Only `home` and `guide` are captured. `/search` is served from the
|
|
162
|
+
SPA fallback (`_mado/spa.html`).
|
|
163
|
+
|
|
164
|
+
## 5. Build-time API call
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
import { html, page } from "@madojs/mado";
|
|
168
|
+
|
|
169
|
+
interface Release { tag: string; date: string }
|
|
170
|
+
|
|
171
|
+
export default page<{ tag: string }, Release>({
|
|
172
|
+
static: {
|
|
173
|
+
paths: async () => {
|
|
174
|
+
const res = await fetch("https://api.github.com/repos/madojs/mado/releases");
|
|
175
|
+
const list = (await res.json()) as Release[];
|
|
176
|
+
return list.map((r) => ({ tag: r.tag }));
|
|
177
|
+
},
|
|
178
|
+
initialData: async ({ tag }) => {
|
|
179
|
+
const res = await fetch(
|
|
180
|
+
`https://api.github.com/repos/madojs/mado/releases/tags/${tag}`,
|
|
181
|
+
);
|
|
182
|
+
return (await res.json()) as Release;
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
title: (_, seed) => `Release ${seed?.tag ?? ""}`,
|
|
186
|
+
view: (ctx) => html`
|
|
187
|
+
<article>
|
|
188
|
+
<h1>${ctx.data.tag}</h1>
|
|
189
|
+
<time>${ctx.data.date}</time>
|
|
190
|
+
</article>
|
|
191
|
+
`,
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Network calls in `paths()` / `initialData()` are perfectly fine — they
|
|
196
|
+
run in the discovery Node process, not in the browser at capture.
|
|
197
|
+
|
|
198
|
+
## 6. Sub-path deployment
|
|
199
|
+
|
|
200
|
+
`mado release` honours Vite's `base`. Configure it once:
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
// vite.config.ts
|
|
204
|
+
import { defineConfig } from "vite";
|
|
205
|
+
import { mado } from "@madojs/mado/vite";
|
|
206
|
+
|
|
207
|
+
export default defineConfig({
|
|
208
|
+
base: "/docs/",
|
|
209
|
+
plugins: [mado({ site: "https://your.site" })],
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Every link in your app must go through `routeUrl()` so it picks up
|
|
214
|
+
the prefix:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { html, routeUrl } from "@madojs/mado";
|
|
218
|
+
|
|
219
|
+
html`<a data-link href=${routeUrl("/guides/intro")}>Intro</a>`;
|
|
220
|
+
html`<a data-link href=${routeUrl("/")}>Home</a>`; // → "/docs/"
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Captured canonicals and `og:url` will be `https://your.site/docs/...`.
|
|
224
|
+
|
|
225
|
+
## 7. SPA-only fallback
|
|
226
|
+
|
|
227
|
+
Any route that does NOT declare `static` is served from
|
|
228
|
+
`out/_mado/spa.html`. That is the right place for authenticated
|
|
229
|
+
zones, search, dashboards, admin tools.
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
// src/pages/app.page.ts
|
|
233
|
+
import { html, page } from "@madojs/mado";
|
|
234
|
+
|
|
235
|
+
// No `static` field — SPA only.
|
|
236
|
+
export default page({
|
|
237
|
+
title: "App",
|
|
238
|
+
view: () => html`<x-app-shell></x-app-shell>`,
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
The fallback is automatically marked `noindex` so search engines do
|
|
243
|
+
not capture the SPA shell.
|
|
244
|
+
|
|
245
|
+
## 8. Failure modes
|
|
246
|
+
|
|
247
|
+
`mado static` fails the snapshot (non-zero exit) when:
|
|
248
|
+
|
|
249
|
+
- A script, stylesheet, custom element or tracked `resource()` fetch
|
|
250
|
+
fails.
|
|
251
|
+
- A custom element is referenced in the rendered DOM but never
|
|
252
|
+
defined.
|
|
253
|
+
- A page declares `static: true` on a route with `:params` but no
|
|
254
|
+
`paths()`.
|
|
255
|
+
- Two pages produce the same generated URL.
|
|
256
|
+
- Any guard runs on a static route or its layout chain.
|
|
257
|
+
- `initialData()` returns a value that is not strictly JSON-serialisable
|
|
258
|
+
(Date, Map, Set, class instance, `undefined` field, NaN, Infinity,
|
|
259
|
+
cycles, non-plain prototypes). The validator points at the bad
|
|
260
|
+
field by path.
|
|
261
|
+
|
|
262
|
+
A failed snapshot leaves the previous `out/` untouched: capture
|
|
263
|
+
writes to a temp tree and only promotes once every route survived.
|
|
264
|
+
|
|
265
|
+
## 9. CI guidance
|
|
266
|
+
|
|
267
|
+
```yaml
|
|
268
|
+
# .github/workflows/ci.yml — extract
|
|
269
|
+
- name: Install Playwright Chromium
|
|
270
|
+
run: node node_modules/playwright-core/cli.js install --with-deps chromium
|
|
271
|
+
|
|
272
|
+
- name: Release smoke
|
|
273
|
+
env:
|
|
274
|
+
MADO_REQUIRE_BROWSER: "1"
|
|
275
|
+
MADO_SITE: "https://your.site"
|
|
276
|
+
run: npm run release
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
`MADO_REQUIRE_BROWSER=1` forces `mado static` to fail loudly if no
|
|
280
|
+
Chromium is resolvable (instead of silently producing a SPA-only
|
|
281
|
+
build).
|
|
282
|
+
|
|
283
|
+
## 10. Quick checklist before pushing
|
|
284
|
+
|
|
285
|
+
- [ ] `mado({ site })` set (or `MADO_SITE` / `--base-url`).
|
|
286
|
+
- [ ] Every static page declares `static: true | { paths, initialData }`.
|
|
287
|
+
- [ ] No `paths()` / `initialData()` reads secrets.
|
|
288
|
+
- [ ] No static page is behind a guard.
|
|
289
|
+
- [ ] Internal links go through `routeUrl()` + `data-link`.
|
|
290
|
+
- [ ] `mado release` succeeds locally with Playwright Chromium
|
|
291
|
+
installed.
|
|
292
|
+
- [ ] `mado preview` serves the artefact correctly.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Devtools and diagnostics
|
|
2
|
+
|
|
3
|
+
Development instrumentation is opt-in and compiled out of production builds.
|
|
4
|
+
Import the stable devtools subpath before application startup:
|
|
5
|
+
|
|
6
|
+
```ts
|
|
7
|
+
import { devtools } from "@madojs/mado/devtools.js";
|
|
8
|
+
|
|
9
|
+
devtools.open();
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`Alt+Shift+M` toggles the Shadow DOM overlay. Its Overview, Reactivity,
|
|
13
|
+
Components, Router/Data and Timeline/Errors views are fed by a versioned
|
|
14
|
+
internal hook. The controller also exposes `close()`, `toggle()`, `clear()`,
|
|
15
|
+
`setLogLevel()` and `snapshot()`. Snapshots contain safe previews rather than
|
|
16
|
+
live application objects.
|
|
17
|
+
|
|
18
|
+
`localStorage.madoDebug = "1"` is accepted during 0.13 migration only and emits
|
|
19
|
+
a deprecation warning.
|
|
20
|
+
|
|
21
|
+
## Runtime diagnostics
|
|
22
|
+
|
|
23
|
+
Every record has `level`, `scope`, `code`, `message`, optional `data`, and a
|
|
24
|
+
timestamp. Set browser verbosity with:
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
localStorage.setItem("mado:log-level", "debug");
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Allowed levels are `debug`, `info`, `warn`, `error` and `silent`. Records are
|
|
31
|
+
also dispatched as `mado:diagnostic` events and appear in devtools.
|
|
32
|
+
|
|
33
|
+
## CLI diagnostics
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
mado release --log-level=debug --log-format=pretty
|
|
37
|
+
mado release --log-format=plain
|
|
38
|
+
mado release --log-format=json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The CLI honours `MADO_LOG_LEVEL`, `MADO_LOG_FORMAT` and `NO_COLOR`. Non-TTY
|
|
42
|
+
output automatically becomes plain. JSON mode writes one structured record per
|
|
43
|
+
line, suitable for CI ingestion.
|
|
44
|
+
|
|
45
|
+
The logger is internal infrastructure, not a public logging API for apps.
|
|
@@ -9,11 +9,11 @@ package root:
|
|
|
9
9
|
import { component, html, resource, routes, signal } from "@madojs/mado";
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
The public package subpaths are the
|
|
13
|
-
|
|
12
|
+
The public package subpaths are the devtools controller and the Vite tooling
|
|
13
|
+
integration:
|
|
14
14
|
|
|
15
15
|
```ts
|
|
16
|
-
import "@madojs/mado/devtools.js";
|
|
16
|
+
import { devtools } from "@madojs/mado/devtools.js";
|
|
17
17
|
import { mado } from "@madojs/mado/vite";
|
|
18
18
|
```
|
|
19
19
|
|
|
@@ -26,18 +26,19 @@ These names are public and protected by SemVer once v1 ships:
|
|
|
26
26
|
|
|
27
27
|
- Reactivity: `signal`, `computed`, `effect`, `untracked`, `batch`,
|
|
28
28
|
`flushSync`.
|
|
29
|
-
- Templates and directives: `html`, `render`, `
|
|
29
|
+
- Templates and directives: `html`, `render`, `unmount`, `each`, `unsafeHTML`,
|
|
30
30
|
`ref`, `classMap`, `styleMap`.
|
|
31
31
|
- Components and CSS: `component`, `css`, `cssVars`.
|
|
32
32
|
- Routing and pages: `routes`, `router`, `page`, `layout`,
|
|
33
|
-
`navigate`, `queryParam`, `prefetchPath`.
|
|
33
|
+
`navigate`, `queryParam`, `prefetchPath`, `routeUrl`, `appBase`.
|
|
34
34
|
- Data: `resource`, `mutation`, `invalidate`, `jsonFetcher`, `HttpError`.
|
|
35
35
|
- Forms: `useForm`.
|
|
36
36
|
- Head and persistence: `applyHead`, `persisted`.
|
|
37
37
|
- Context: `createContext`, `provide`, `inject`.
|
|
38
38
|
- Advanced lifecycle helpers: `createLifecycle`, `runInLifecycle`,
|
|
39
39
|
`getCurrentLifecycle`.
|
|
40
|
-
- Public TypeScript types exported from `@madojs/mado
|
|
40
|
+
- Public TypeScript types exported from `@madojs/mado`, including `FormApi`,
|
|
41
|
+
`Resource`, `ComponentContext`, `StaticPageConfig` and `HeadMeta`.
|
|
41
42
|
|
|
42
43
|
## Internal or unstable
|
|
43
44
|
|
|
@@ -48,7 +49,14 @@ These are not public API:
|
|
|
48
49
|
- Template parser/binding internals such as `html/parser.js`,
|
|
49
50
|
`html/bindings.js`, `ChildState`, and `EachEntry`.
|
|
50
51
|
- Router implementation modules such as `router/match.js`,
|
|
51
|
-
`router/navigation.js`, and `router/
|
|
52
|
+
`router/navigation.js`, `router/manifest.js`, and `router/base.js`.
|
|
53
|
+
- Base-path helpers other than `routeUrl` / `appBase`: `normalizeBase`,
|
|
54
|
+
`stripBase` and `withBase` are intentionally not exported from
|
|
55
|
+
`@madojs/mado`. Use `routeUrl()` for `<a href>` values and `appBase`
|
|
56
|
+
if you need the raw active prefix.
|
|
57
|
+
- The static snapshot pipeline (`scripts/static.mjs`, the
|
|
58
|
+
`_mado/build.json` bridge, the temp capture server). `mado static` is
|
|
59
|
+
a CLI command; its internals can change between minor versions.
|
|
52
60
|
- Diagnostics internals and all `_testHooks`.
|
|
53
61
|
- Exact generated bundle text, chunk names, and internal file layout.
|
|
54
62
|
|
|
@@ -57,8 +65,8 @@ Application code should not.
|
|
|
57
65
|
|
|
58
66
|
## What can change
|
|
59
67
|
|
|
60
|
-
Patch and minor releases may add
|
|
61
|
-
|
|
68
|
+
Patch and minor releases may add compatible options, diagnostics, docs or
|
|
69
|
+
starter files. New root exports require an explicit API review. Releases may change internals, emitted bundle shape, and
|
|
62
70
|
implementation details as long as the stable API and documented behavior remain
|
|
63
71
|
compatible.
|
|
64
72
|
|
|
@@ -8,8 +8,8 @@ copy, or diagnostic string is frozen forever.
|
|
|
8
8
|
|
|
9
9
|
Read this together with:
|
|
10
10
|
|
|
11
|
-
- [API freeze map](./
|
|
12
|
-
- [Reactivity ordering](./
|
|
11
|
+
- [API freeze map](./30-api-freeze-map.md)
|
|
12
|
+
- [Reactivity ordering](./31-reactivity-ordering.md)
|
|
13
13
|
|
|
14
14
|
## Stable under SemVer
|
|
15
15
|
|
|
@@ -17,7 +17,7 @@ After v1, Mado treats these as SemVer-protected:
|
|
|
17
17
|
|
|
18
18
|
- Public exports from `@madojs/mado`.
|
|
19
19
|
- Public TypeScript types exported from `@madojs/mado`.
|
|
20
|
-
- The `@madojs/mado/devtools.js`
|
|
20
|
+
- The `@madojs/mado/devtools.js` controller subpath and `@madojs/mado/vite`.
|
|
21
21
|
- Template binding syntax: child `${}`, `@event`, `.prop`, `?boolean`,
|
|
22
22
|
attribute bindings, directives and `each()`.
|
|
23
23
|
- Signal semantics documented in the reactivity ordering guide.
|
|
@@ -25,7 +25,7 @@ After v1, Mado treats these as SemVer-protected:
|
|
|
25
25
|
teardown for same-tick moves, cleanup via `ctx.onDispose`.
|
|
26
26
|
- Router/page/resource/form contracts documented in the English docs.
|
|
27
27
|
- CLI command names and broad command intent (`build`, `dev`, `release`,
|
|
28
|
-
`
|
|
28
|
+
`static`, `preview`, `init`, `new`).
|
|
29
29
|
|
|
30
30
|
Breaking these requires a major version.
|
|
31
31
|
|
|
@@ -33,7 +33,7 @@ Breaking these requires a major version.
|
|
|
33
33
|
|
|
34
34
|
Minor releases may add:
|
|
35
35
|
|
|
36
|
-
- New root exports.
|
|
36
|
+
- New root exports after explicit API review and golden-file update.
|
|
37
37
|
- New options on existing APIs.
|
|
38
38
|
- New diagnostics and warnings.
|
|
39
39
|
- New starters, examples, docs and CLI flags.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Migrating from 0.12 to 0.13
|
|
2
|
+
|
|
3
|
+
0.13 is the final planned pre-v1 breaking release. It narrows the root API and
|
|
4
|
+
makes lifecycle, forms, resources and router behaviour explicit.
|
|
5
|
+
|
|
6
|
+
## Forms
|
|
7
|
+
|
|
8
|
+
<!-- docs-lint:allow-legacy-mention -->
|
|
9
|
+
|
|
10
|
+
The 0.12 schema-shaped call:
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
useForm({ email: { required: true, type: "email" } });
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
becomes:
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
useForm({ initial: { email: "" } });
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Move `required`, `type`, `min`, `max` and `pattern` to the native controls.
|
|
23
|
+
Replace `setValue` with `setField`. The separate field-array helper was removed;
|
|
24
|
+
use ordinary array values and `setField`. Custom/async validation now belongs
|
|
25
|
+
to `validate(values, { signal, form })` in the options object.
|
|
26
|
+
|
|
27
|
+
<!-- /docs-lint:allow-legacy-mention -->
|
|
28
|
+
|
|
29
|
+
## Removed root exports
|
|
30
|
+
|
|
31
|
+
`lazy`, `list`, `instantiate`, `isHtmlDirective`, `adopt`, `scopeStyles`,
|
|
32
|
+
`isPage` and `isLayoutGroup` are no longer root exports. Use dynamic route
|
|
33
|
+
imports, `each()`, `render()` and the documented high-level APIs instead.
|
|
34
|
+
Only the package root, `/vite` and `/devtools.js` are public subpaths.
|
|
35
|
+
|
|
36
|
+
## Behaviour changes
|
|
37
|
+
|
|
38
|
+
- `render()` returns an idempotent disposer; `unmount(container)` explicitly
|
|
39
|
+
releases bindings, events, nested templates and child lifecycles.
|
|
40
|
+
- `page.load` is synchronous. Return a value or a `Resource`; returning a
|
|
41
|
+
Promise throws a diagnostic error. Put async work in `resource()`.
|
|
42
|
+
- `resource().refresh()` returns `Promise<T>`. `staleTime: 0` deduplicates only
|
|
43
|
+
an in-flight request and never reuses completed data.
|
|
44
|
+
- Cache identity includes the fetcher, and `invalidate()` reaches cached and
|
|
45
|
+
uncached live resources.
|
|
46
|
+
- Persisted signals separate `dispose()` from explicit storage deletion.
|
|
47
|
+
- Context now uses the Web Components `context-request` protocol and cleans up
|
|
48
|
+
subscriptions with the current lifecycle.
|
|
49
|
+
- Static capture blocks undeclared external requests and `mado build` writes
|
|
50
|
+
the `out/` artifact consumed by `mado static`.
|
|
51
|
+
|
|
52
|
+
## Devtools and logging
|
|
53
|
+
|
|
54
|
+
Import `@madojs/mado/devtools.js` in development and use `Alt+Shift+M`.
|
|
55
|
+
`localStorage.madoDebug` is deprecated; use `mado:log-level` or the controller.
|
|
56
|
+
CLI automation should prefer `--log-format=json`.
|