@madojs/mado 0.8.0 → 0.10.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 (83) hide show
  1. package/AGENTS.md +81 -4
  2. package/CHANGELOG.md +202 -1
  3. package/README.md +184 -242
  4. package/ROADMAP.md +174 -79
  5. package/TODO.md +8 -5
  6. package/dist/src/component.d.ts +2 -12
  7. package/dist/src/component.js +30 -29
  8. package/dist/src/component.js.map +1 -1
  9. package/dist/src/diagnostics.d.ts +0 -4
  10. package/dist/src/diagnostics.js +1 -0
  11. package/dist/src/diagnostics.js.map +1 -1
  12. package/dist/src/forms.js +17 -0
  13. package/dist/src/forms.js.map +1 -1
  14. package/dist/src/html/bindings.js +35 -3
  15. package/dist/src/html/bindings.js.map +1 -1
  16. package/dist/src/html/parser.js +60 -3
  17. package/dist/src/html/parser.js.map +1 -1
  18. package/dist/src/lifecycle.js +18 -0
  19. package/dist/src/lifecycle.js.map +1 -1
  20. package/dist/src/persisted.js +43 -9
  21. package/dist/src/persisted.js.map +1 -1
  22. package/dist/src/resource.d.ts +13 -6
  23. package/dist/src/resource.js +83 -16
  24. package/dist/src/resource.js.map +1 -1
  25. package/dist/src/router/manifest.d.ts +0 -3
  26. package/dist/src/router/manifest.js +23 -2
  27. package/dist/src/router/manifest.js.map +1 -1
  28. package/dist/src/router/navigation.js +56 -2
  29. package/dist/src/router/navigation.js.map +1 -1
  30. package/dist/src/router.d.ts +1 -1
  31. package/dist/src/router.js +1 -1
  32. package/dist/src/router.js.map +1 -1
  33. package/dist/src/signal.d.ts +0 -4
  34. package/dist/src/signal.js +56 -7
  35. package/dist/src/signal.js.map +1 -1
  36. package/docs/en/00-the-mado-way.md +23 -12
  37. package/docs/en/03-static-bake.md +1 -2
  38. package/docs/en/05-why-mado.md +78 -68
  39. package/docs/en/06-for-backenders.md +80 -55
  40. package/docs/en/07-llm-pitfalls.md +101 -0
  41. package/docs/en/08-llm-zero-history-test.md +5 -0
  42. package/docs/en/18-api-freeze-map.md +63 -0
  43. package/docs/en/19-reactivity-ordering.md +93 -0
  44. package/docs/en/20-v1-stability.md +83 -0
  45. package/docs/en/README.md +3 -0
  46. package/docs/fr/00-the-mado-way.md +25 -13
  47. package/docs/fr/03-static-bake.md +1 -2
  48. package/docs/fr/06-for-backenders.md +6 -0
  49. package/docs/fr/07-llm-pitfalls.md +2 -0
  50. package/docs/fr/08-llm-zero-history-test.md +5 -0
  51. package/docs/fr/18-api-freeze-map.md +63 -0
  52. package/docs/fr/19-reactivity-ordering.md +97 -0
  53. package/docs/fr/20-v1-stability.md +88 -0
  54. package/docs/fr/README.md +3 -0
  55. package/docs/ru/00-the-mado-way.md +24 -11
  56. package/docs/ru/03-static-bake.md +2 -3
  57. package/docs/ru/06-for-backenders.md +6 -0
  58. package/docs/ru/07-llm-pitfalls.md +2 -0
  59. package/docs/ru/08-llm-zero-history-test.md +5 -0
  60. package/docs/ru/18-api-freeze-map.md +62 -0
  61. package/docs/ru/19-reactivity-ordering.md +95 -0
  62. package/docs/ru/20-v1-stability.md +82 -0
  63. package/docs/ru/README.md +3 -0
  64. package/docs/uk/00-the-mado-way.md +3 -1
  65. package/docs/uk/06-for-backenders.md +5 -0
  66. package/docs/uk/07-llm-pitfalls.md +2 -0
  67. package/docs/uk/08-llm-zero-history-test.md +5 -0
  68. package/docs/uk/18-api-freeze-map.md +61 -0
  69. package/docs/uk/19-reactivity-ordering.md +95 -0
  70. package/docs/uk/20-v1-stability.md +83 -0
  71. package/docs/uk/README.md +3 -0
  72. package/llms.txt +63 -7
  73. package/package.json +10 -5
  74. package/scripts/bake.mjs +0 -1
  75. package/scripts/bundle.mjs +6 -6
  76. package/scripts/cli.mjs +17 -0
  77. package/scripts/llm-zero-history-smoke.mjs +93 -0
  78. package/scripts/new.mjs +1 -1
  79. package/scripts/package-smoke.mjs +74 -0
  80. package/scripts/size-budget.mjs +88 -0
  81. package/starters/admin/package.json +2 -2
  82. package/starters/crud/package.json +2 -2
  83. package/starters/minimal/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"signal.js","sourceRoot":"","sources":["../../src/signal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"signal.js","sourceRoot":"","sources":["../../src/signal.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,10 @@
2
2
 
3
3
  > One right way. Strict contracts. No magic.
4
4
 
5
- Mado is not just a framework it is a **set of conventions**. If you follow them,
6
- the project stays understandable even with 200 screens and 5 developers. If you
5
+ Mado is a framework for teams building admin panels, internal tools and
6
+ business SPA apps that should be easy to build and boring to maintain. To
7
+ achieve that, it enforces a **set of conventions**. If you follow them, the
8
+ project stays understandable even with 200 screens and 5 developers. If you
7
9
  break them — types and the linter will tell you immediately.
8
10
 
9
11
  ## Principles
@@ -40,13 +42,21 @@ all write the same way.
40
42
 
41
43
  ```ts
42
44
  // src/components/user-card.ts
43
- import { component, html, css } from '@madojs/mado';
44
-
45
- component('x-user-card', () => {
46
- return () => html`<div class="card"><slot/></div>`;
47
- }, {
48
- styles: css`.card { padding: 1rem; }`,
49
- });
45
+ import { component, html, css } from "@madojs/mado";
46
+
47
+ component(
48
+ "x-user-card",
49
+ () => {
50
+ return () => html`<div class="card"><slot /></div>`;
51
+ },
52
+ {
53
+ styles: css`
54
+ .card {
55
+ padding: 1rem;
56
+ }
57
+ `,
58
+ },
59
+ );
50
60
  ```
51
61
 
52
62
  `import './components/user-card.js'` **registers** the component via
@@ -61,7 +71,7 @@ component('x-user-card', () => {
61
71
  const user = resource(() => `/api/users/${id()}`, jsonFetcher());
62
72
 
63
73
  // writing → mutation
64
- const save = mutation(api.save, { invalidates: ['/api/users*'] });
74
+ const save = mutation(api.save, { invalidates: ["/api/users*"] });
65
75
  ```
66
76
 
67
77
  This provides caching, cancellation, error handling, and auto-invalidation.
@@ -70,11 +80,11 @@ This provides caching, cancellation, error handling, and auto-invalidation.
70
80
 
71
81
  ```ts
72
82
  // src/pages/user-profile.ts
73
- import { page, html, resource, jsonFetcher } from '@madojs/mado';
83
+ import { page, html, resource, jsonFetcher } from "@madojs/mado";
74
84
 
75
85
  export default page({
76
86
  title: ({ id }) => `User #${id}`,
77
- view: ({ params }) => html`...`,
87
+ view: ({ params }) => html`...`,
78
88
  });
79
89
  ```
80
90
 
@@ -99,6 +109,7 @@ See [`01-routing.md`](./01-routing.md).
99
109
  ## When in doubt
100
110
 
101
111
  If you are asking "what's the best way here?" — that is a signal that:
112
+
102
113
  1. Either there is a built-in helper you don't know about (check `docs/`).
103
114
  2. Or this is a new situation — discuss it and **record** it in this document
104
115
  as one more convention.
@@ -129,7 +129,6 @@ out/
129
129
  {"@context":"https://schema.org","@type":"Product","..."}
130
130
  </script>
131
131
  <meta name="bake-revalidate" content="3600" data-mado-head="baked">
132
- <meta name="bake-stamp" content="1234567890" data-mado-head="baked">
133
132
  </head>
134
133
  <body>
135
134
  <div id="app">
@@ -212,7 +211,7 @@ export default page<{ slug: string }>({
212
211
 
213
212
  ## Revalidate / CDN
214
213
 
215
- `bake.revalidate: 3600` writes `<meta name="bake-revalidate" content="3600">` and `bake-stamp` to the HTML. This is **metadata** — the framework does not re-bake anything itself. Strategies:
214
+ `bake.revalidate: 3600` writes `<meta name="bake-revalidate" content="3600">` to the HTML. This is **metadata** — the framework does not re-bake anything itself. Strategies:
216
215
 
217
216
  1. **Simplest option**: cron in CI — `npm run bake && rsync out/ origin:/var/www/`.
218
217
  2. **Via CDN** (Cloudflare/Fastly): serve HTML with `Cache-Control: max-age=3600`. CDN invalidates itself.
@@ -1,22 +1,27 @@
1
1
  # Why Mado (and why not Lit / Solid / Alpine / htmx)
2
2
 
3
- > If you are choosing a frontend stack for a new project, this page is for you.
4
- > If you already have something working — **don't migrate for the sake of migration**, it always costs more than it seems.
3
+ > If you are choosing a frontend stack for an admin panel, internal tool or
4
+ > business SPA, this page is for you.
5
+ > If you already have something working — **don't migrate for the sake of
6
+ > migration**, it always costs more than it seems.
5
7
 
6
- Mado is not a "killer" of React/Vue/Svelte. It is a narrowly specialized tool. Here I honestly explain **in which cases Mado is genuinely better than the alternatives**, and in which it is not.
8
+ Mado is not a "killer" of React/Vue/Svelte. It is a focused tool for teams that
9
+ want a complete app stack (routing, forms, data, state, prerender) without
10
+ frontend infrastructure overhead. Here is an honest comparison of **when Mado is
11
+ genuinely better than the alternatives**, and when it is not.
7
12
 
8
13
  ---
9
14
 
10
15
  ## TL;DR — one table
11
16
 
12
- | If you care about… | Choose |
13
- |---|---|
14
- | Best learning infrastructure / huge ecosystem | **React** or **Vue** |
15
- | Component design system for embedding into any framework | **Lit** |
16
- | Top performance on large lists, "close to vanilla" with JSX | **Solid** or **Svelte 5** |
17
- | Progressive enhancement of classic server-rendered apps | **htmx** + your backend |
18
- | "Sprinkling" reactivity onto a static site | **Alpine.js** |
19
- | Minimal tooling, maximum platform, everything in one box (router + data + forms + SEO), readable in an evening | **Mado** ✓ |
17
+ | If you care about… | Choose |
18
+ | -------------------------------------------------------------------------------------------------------------- | ------------------------- |
19
+ | Best learning infrastructure / huge ecosystem | **React** or **Vue** |
20
+ | Component design system for embedding into any framework | **Lit** |
21
+ | Top performance on large lists, "close to vanilla" with JSX | **Solid** or **Svelte 5** |
22
+ | Progressive enhancement of classic server-rendered apps | **htmx** + your backend |
23
+ | "Sprinkling" reactivity onto a static site | **Alpine.js** |
24
+ | Minimal tooling, maximum platform, everything in one box (router + data + forms + SEO), readable in an evening | **Mado** ✓ |
20
25
 
21
26
  If your case does not fall into the last point — Mado is most likely not the best choice. That's fine.
22
27
 
@@ -26,21 +31,21 @@ If your case does not fall into the last point — Mado is most likely not the b
26
31
 
27
32
  **Lit** is the closest alternative in spirit. Same approach: Web Components + tagged templates + minimal magic.
28
33
 
29
- | | Lit | Mado |
30
- |---|---|---|
31
- | Size | ~6 KB | ~16 KB |
32
- | Age / support | ~10 years, Google | 6 months, single author |
33
- | Reactivity | `@property` decorators + manual `requestUpdate` | signals (`signal`/`computed`/`effect`) out of the box |
34
- | Router | none, you need to find one (`@lit-labs/router`, etc) | included: `routes()` + nested + prefetch + sync-cache |
35
- | Data fetching | none, you need to assemble it | `resource()` + `mutation()` + glob invalidation |
36
- | Forms | none | `useForm()` with HTML-like constraints |
37
- | SEO / static | complex (`@lit-labs/ssr`) | `bake` (linkedom) + edge-prerender |
38
- | Build | needs esbuild/rollup/webpack | `tsc` is enough |
39
- | Code style | classes + decorators | functions + tagged templates |
40
- | Ecosystem | real (Shoelace, Material Web, etc.) | none |
34
+ | | Lit | Mado |
35
+ | -------------- | -------------------------------------------------------------- | ------------------------------------------------------ |
36
+ | Size | ~6 KB | ~16 KB |
37
+ | Age / support | ~10 years, Google | 6 months, single author |
38
+ | Reactivity | `@property` decorators + manual `requestUpdate` | signals (`signal`/`computed`/`effect`) out of the box |
39
+ | Router | none, you need to find one (`@lit-labs/router`, etc) | included: `routes()` + nested + prefetch + sync-cache |
40
+ | Data fetching | none, you need to assemble it | `resource()` + `mutation()` + glob invalidation |
41
+ | Forms | none | `useForm()` with HTML-like constraints |
42
+ | SEO / static | complex (`@lit-labs/ssr`) | `bake` (linkedom) + edge-prerender |
43
+ | Build | needs esbuild/rollup/webpack | `tsc` is enough |
44
+ | Code style | classes + decorators | functions + tagged templates |
45
+ | Ecosystem | real (Shoelace, Material Web, etc.) | none |
41
46
  | When to choose | writing a design system / Web Components library for embedding | writing a full application, want everything in one box |
42
47
 
43
- **Honest pitch:** *"Lit is better if you're writing a component design system. Mado is better if you're writing an application and want batteries included without assembling 8 packages."*
48
+ **Honest pitch:** _"Lit is better if you're writing a component design system. Mado is better if you're writing an application and want batteries included without assembling 8 packages."_
44
49
 
45
50
  ---
46
51
 
@@ -48,21 +53,21 @@ If your case does not fall into the last point — Mado is most likely not the b
48
53
 
49
54
  **Solid** is a top-tier reactive library built on signals. Technically very impressive.
50
55
 
51
- | | Solid | Mado |
52
- |---|---|---|
53
- | Size | ~7 KB | ~16 KB |
54
- | Performance | top-3 on js-framework-benchmark | good, but not top |
55
- | Reactivity | signals (same class of ideas) | signals |
56
- | Templates | JSX (compiled to reactive expressions) | tagged template `html\`\`` |
57
- | Component model | functions, Solid virtual nodes | Web Components |
58
- | Build | Vite + babel-plugin-solid required | `tsc` only |
59
- | Router | `@solidjs/router` | included |
60
- | Data | `createResource` | `resource()` |
61
- | SSR | seriously supported (SolidStart) | intentionally none |
62
- | Ecosystem | growing, ~50 packages | none |
63
- | When to choose | need top performance + JSX + willing to configure the build | want to run without a build / minimal infrastructure |
64
-
65
- **Honest pitch:** *"Solid is technically faster and more mature. But Solid requires Vite + a babel plugin. Mado requires nothing but `tsc` — it's 'open VS Code, F5, and work'. If that difference isn't critical — go with Solid."*
56
+ | | Solid | Mado |
57
+ | --------------- | ----------------------------------------------------------- | ---------------------------------------------------- |
58
+ | Size | ~7 KB | ~16 KB |
59
+ | Performance | top-3 on js-framework-benchmark | good, but not top |
60
+ | Reactivity | signals (same class of ideas) | signals |
61
+ | Templates | JSX (compiled to reactive expressions) | tagged template `html\`\`` |
62
+ | Component model | functions, Solid virtual nodes | Web Components |
63
+ | Build | Vite + babel-plugin-solid required | `tsc` only |
64
+ | Router | `@solidjs/router` | included |
65
+ | Data | `createResource` | `resource()` |
66
+ | SSR | seriously supported (SolidStart) | intentionally none |
67
+ | Ecosystem | growing, ~50 packages | none |
68
+ | When to choose | need top performance + JSX + willing to configure the build | want to run without a build / minimal infrastructure |
69
+
70
+ **Honest pitch:** _"Solid is technically faster and more mature. But Solid requires Vite + a babel plugin. Mado requires nothing but `tsc` — it's 'open VS Code, F5, and work'. If that difference isn't critical — go with Solid."_
66
71
 
67
72
  ---
68
73
 
@@ -70,17 +75,17 @@ If your case does not fall into the last point — Mado is most likely not the b
70
75
 
71
76
  **Svelte 5** with runes — also a signal model, also minimalist.
72
77
 
73
- | | Svelte 5 | Mado |
74
- |---|---|---|
75
- | Runtime size | ~3 KB | ~16 KB |
76
- | Compiler | required (.svelte → JS) | none |
77
- | Syntax | custom .svelte format | TS + tagged templates |
78
- | Reactivity | `$state`/`$derived` (runes) | `signal`/`computed` |
79
- | SSR / SvelteKit | full-featured, mature | intentionally none |
80
- | Ecosystem | large, excellent dev-tools | none |
81
- | When to choose | new production project with a team | private/internal tool, need simplicity |
78
+ | | Svelte 5 | Mado |
79
+ | --------------- | ---------------------------------- | -------------------------------------- |
80
+ | Runtime size | ~3 KB | ~16 KB |
81
+ | Compiler | required (.svelte → JS) | none |
82
+ | Syntax | custom .svelte format | TS + tagged templates |
83
+ | Reactivity | `$state`/`$derived` (runes) | `signal`/`computed` |
84
+ | SSR / SvelteKit | full-featured, mature | intentionally none |
85
+ | Ecosystem | large, excellent dev-tools | none |
86
+ | When to choose | new production project with a team | private/internal tool, need simplicity |
82
87
 
83
- **Honest pitch:** *"Svelte is a product choice. Mado is an engineering one. If you have a team and a production app — Svelte. If you're alone and want control — Mado."*
88
+ **Honest pitch:** _"Svelte is a product choice. Mado is an engineering one. If you have a team and a production app — Svelte. If you're alone and want control — Mado."_
84
89
 
85
90
  ---
86
91
 
@@ -88,17 +93,17 @@ If your case does not fall into the last point — Mado is most likely not the b
88
93
 
89
94
  **htmx** is a different school: HTML-fragments over the wire.
90
95
 
91
- | | htmx | Mado |
92
- |---|---|---|
93
- | Architecture | HTML from server, updated via fragments | SPA: JS loads data, renders itself |
94
- | Backend dependency | strong (backend must be able to serve HTML) | weak (backend is a JSON API) |
95
- | Client state | minimal (cookies, localStorage) | full (signal, persisted) |
96
- | Optimistic updates | difficult | easy (mutation + invalidates) |
97
- | Offline / PWA | poor | decent |
98
- | Size | ~14 KB | ~16 KB |
99
- | When to choose | classic server-rendered app (Rails, Django, Phoenix), need to "liven up" | SPA experience is required, backend is REST/GraphQL |
96
+ | | htmx | Mado |
97
+ | ------------------ | ------------------------------------------------------------------------ | --------------------------------------------------- |
98
+ | Architecture | HTML from server, updated via fragments | SPA: JS loads data, renders itself |
99
+ | Backend dependency | strong (backend must be able to serve HTML) | weak (backend is a JSON API) |
100
+ | Client state | minimal (cookies, localStorage) | full (signal, persisted) |
101
+ | Optimistic updates | difficult | easy (mutation + invalidates) |
102
+ | Offline / PWA | poor | decent |
103
+ | Size | ~14 KB | ~16 KB |
104
+ | When to choose | classic server-rendered app (Rails, Django, Phoenix), need to "liven up" | SPA experience is required, backend is REST/GraphQL |
100
105
 
101
- **Honest pitch:** *"htmx — if the backend is solid and can serve HTML. Mado — if the backend serves JSON and you need a full SPA experience."*
106
+ **Honest pitch:** _"htmx — if the backend is solid and can serve HTML. Mado — if the backend serves JSON and you need a full SPA experience."_
102
107
 
103
108
  ---
104
109
 
@@ -106,16 +111,16 @@ If your case does not fall into the last point — Mado is most likely not the b
106
111
 
107
112
  **Alpine** — reactive attributes directly in HTML.
108
113
 
109
- | | Alpine | Mado |
110
- |---|---|---|
111
- | Purpose | enhancing static HTML | full SPA |
112
- | Size | ~7 KB | ~16 KB |
113
- | State management | `x-data` locally | signals + context + persisted |
114
- | Routing | none | included |
115
- | TypeScript | poor | first-class |
116
- | When to choose | static sites, landing pages, need 5 interactive buttons | full app: pages, navigation, forms, data |
114
+ | | Alpine | Mado |
115
+ | ---------------- | ------------------------------------------------------- | ---------------------------------------- |
116
+ | Purpose | enhancing static HTML | full SPA |
117
+ | Size | ~7 KB | ~16 KB |
118
+ | State management | `x-data` locally | signals + context + persisted |
119
+ | Routing | none | included |
120
+ | TypeScript | poor | first-class |
121
+ | When to choose | static sites, landing pages, need 5 interactive buttons | full app: pages, navigation, forms, data |
117
122
 
118
- **Honest pitch:** *"Alpine — for interactivity on static sites. Mado — for a full application."*
123
+ **Honest pitch:** _"Alpine — for interactivity on static sites. Mado — for a full application."_
119
124
 
120
125
  ---
121
126
 
@@ -124,12 +129,14 @@ If your case does not fall into the last point — Mado is most likely not the b
124
129
  I won't dwell on this for long, because React is in a **different weight class** in terms of ecosystem and maturity. But if you're seriously comparing:
125
130
 
126
131
  **React wins:**
132
+
127
133
  - massive ecosystem: thousands of UI kits, thousands of articles, endless tutorials;
128
134
  - AI assistants (ChatGPT, Copilot) know React better than anything;
129
135
  - better job market;
130
136
  - better SSR support (Next.js).
131
137
 
132
138
  **Mado wins:**
139
+
133
140
  - bundle size dozens of times smaller;
134
141
  - zero infrastructure (no Vite, no Babel, no 200 packages);
135
142
  - readable in an evening — if something breaks, open `src/`;
@@ -137,11 +144,13 @@ I won't dwell on this for long, because React is in a **different weight class**
137
144
  - no need to migrate between major versions.
138
145
 
139
146
  **When to choose Mado over React:**
147
+
140
148
  - 1–3 person project, for years to come;
141
149
  - bundle size is critical;
142
150
  - you're tired of React fatigue and are ready to sacrifice the ecosystem for simplicity.
143
151
 
144
152
  **When to choose React:**
153
+
145
154
  - team of 5 or more people;
146
155
  - you need UI kits, you need the ecosystem;
147
156
  - a project that will be hiring new people from the market;
@@ -166,6 +175,7 @@ For backend developers who are used to small, understandable libraries (chi in G
166
175
  Honestly: **Mado is not the fastest**. The top-3 on js-framework-benchmark are Solid, Inferno, and Svelte. Mado is closer to Lit / Preact in characteristics.
167
176
 
168
177
  What Mado does for performance out of the box:
178
+
169
179
  - **lazy `computed`** (dirty-flag, not eager);
170
180
  - **batch microtask scheduler** for `signal.set`;
171
181
  - **keyed reconciliation** in `each()` with real DOM reuse;
@@ -1,6 +1,7 @@
1
1
  # Mado for Backend Developers
2
2
 
3
- > You write in Go / Rust / .NET / Java / Python and you need to build a web UI.
3
+ > You write in Go / Rust / .NET / Java / Python and you need to build a web UI
4
+ > for an admin panel, internal tool or dashboard.
4
5
  > This page is the mental model of Mado in 10 minutes, in your language.
5
6
 
6
7
  ---
@@ -9,17 +10,17 @@
9
10
 
10
11
  Mado is structured **like an HTTP server**. Seriously:
11
12
 
12
- | Server world | Mado |
13
- |---|---|
14
- | HTTP router (chi, axum, mux) | `routes()` — path manifest |
15
- | Handler `func(req, resp)` | `page({ view: (ctx) => html\`...\` })` |
16
- | Middleware | `layout` in `nested()` (wraps the handler) |
17
- | Template engine (Jinja, Handlebars) | `html\`\`` tagged template |
18
- | HTTP client with cache | `resource()` — fetch + cache + invalidation |
19
- | Reactive variable / atom | `signal()` — reactive getter |
20
- | Background goroutine / task | `effect()` — auto-reruns when a signal changes |
21
- | `defer cleanup()` | `ctx.onDispose(fn)` in component setup |
22
- | ENV variables | `createContext()` + `provide()`/`inject()` |
13
+ | Server world | Mado |
14
+ | ----------------------------------- | ---------------------------------------------- |
15
+ | HTTP router (chi, axum, mux) | `routes()` — path manifest |
16
+ | Handler `func(req, resp)` | `page({ view: (ctx) => html\`...\` })` |
17
+ | Middleware | `layout` in `nested()` (wraps the handler) |
18
+ | Template engine (Jinja, Handlebars) | `html\`\`` tagged template |
19
+ | HTTP client with cache | `resource()` — fetch + cache + invalidation |
20
+ | Reactive variable / atom | `signal()` — reactive getter |
21
+ | Background goroutine / task | `effect()` — auto-reruns when a signal changes |
22
+ | `defer cleanup()` | `ctx.onDispose(fn)` in component setup |
23
+ | ENV variables | `createContext()` + `provide()`/`inject()` |
23
24
 
24
25
  If you understand an HTTP server, you understand Mado.
25
26
 
@@ -130,26 +131,34 @@ import { resource, mutation, jsonFetcher, invalidate } from "@madojs/mado";
130
131
  const userId = signal(1);
131
132
 
132
133
  const user = resource(
133
- () => `/api/users/${userId()}`, // cache key (reactive!)
134
- jsonFetcher<User>(), // how to load
135
- { staleTime: 60_000 }, // 60-second cache
134
+ () => `/api/users/${userId()}`, // cache key (reactive!)
135
+ jsonFetcher<User>(), // how to load
136
+ { staleTime: 60_000 }, // 60-second cache
136
137
  );
137
138
 
138
139
  // in the component:
139
- user.data(); // User | undefined
140
- user.error(); // Error | null
141
- user.loading(); // boolean
140
+ user.data(); // User | undefined
141
+ user.error(); // Error | null
142
+ user.loading(); // boolean
142
143
 
143
144
  // mutation (like POST/PUT)
144
145
  const save = mutation<User, User>(
145
- (u) => fetch("/api/users", { method: "POST", body: JSON.stringify(u) }).then(r => r.json()),
146
- { invalidates: ["/api/users*"] }, // glob invalidation like `cache.Drop("users:*")`
146
+ (u) =>
147
+ fetch("/api/users", { method: "POST", body: JSON.stringify(u) }).then((r) =>
148
+ r.json(),
149
+ ),
150
+ { invalidates: ["/api/users*"] }, // glob invalidation — like `cache.Drop("users:*")`
147
151
  );
148
152
 
149
153
  await save.run(newUser);
150
154
  // automatically: user.data() will update if glob matches
151
155
  ```
152
156
 
157
+ Resource keys are cache identities. Include the endpoint, query params and data
158
+ shape in the key: two live `resource()` calls with the same key share cached
159
+ data and any in-flight request. If two different fetchers use the same in-flight
160
+ key, Mado warns because that usually means the cache key is too broad.
161
+
153
162
  If such an abstraction existed in the Go world for server-side caches — we'd all be crying with joy.
154
163
 
155
164
  ---
@@ -169,9 +178,7 @@ component("x-counter", () => {
169
178
  const count = signal(0);
170
179
 
171
180
  return () => html`
172
- <button @click=${() => count.update(n => n + 1)}>
173
- Clicks: ${count}
174
- </button>
181
+ <button @click=${() => count.update((n) => n + 1)}>Clicks: ${count}</button>
175
182
  `;
176
183
  });
177
184
  ```
@@ -179,7 +186,7 @@ component("x-counter", () => {
179
186
  Usage:
180
187
 
181
188
  ```ts
182
- html`<x-counter></x-counter>`
189
+ html`<x-counter></x-counter>`;
183
190
  ```
184
191
 
185
192
  We register the `<x-counter>` tag in the browser — it becomes a "function" that can be inserted into HTML. This is a **native** browser mechanism (Web Components), Mado only glues it together with signals.
@@ -195,22 +202,29 @@ import { useForm } from "@madojs/mado";
195
202
 
196
203
  const f = useForm({
197
204
  email: { required: true, type: "email" },
198
- age: { required: true, type: "number", min: 18 },
205
+ age: { required: true, type: "number", min: 18 },
199
206
  });
200
207
 
201
208
  // in the template:
202
209
  html`
203
- <form @submit=${f.onSubmit(async (v) => {
204
- await api.save(v);
205
- f.reset();
206
- })}>
207
- <input name="email" .value=${() => f.values().email ?? ""}
208
- @input=${f.onInput} @blur=${f.onBlur} />
209
-
210
- ${() => f.errors().email && f.touched().email
211
- ? html`<small>${f.errors().email}</small>`
212
- : null}
213
-
210
+ <form
211
+ @submit=${f.onSubmit(async (v) => {
212
+ await api.save(v);
213
+ f.reset();
214
+ })}
215
+ >
216
+ <input
217
+ name="email"
218
+ .value=${() => f.values().email ?? ""}
219
+ @input=${f.onInput}
220
+ @blur=${f.onBlur}
221
+ />
222
+
223
+ ${() =>
224
+ f.errors().email && f.touched().email
225
+ ? html`<small>${f.errors().email}</small>`
226
+ : null}
227
+
214
228
  <button ?disabled=${() => !f.isValid() || f.submitting()}>Save</button>
215
229
  </form>
216
230
  `;
@@ -233,12 +247,12 @@ const ApiCtx = createContext<ApiClient>(defaultApiClient);
233
247
  // in the root component — provide
234
248
  component("x-app", ({ host }) => {
235
249
  provide(host, ApiCtx, new ApiClient("https://api.example.com"));
236
- return () => html`<x-page/>`;
250
+ return () => html`<x-page />`;
237
251
  });
238
252
 
239
253
  // in any child — consume
240
254
  component("x-page", ({ host }) => {
241
- const api = inject(host, ApiCtx); // signal<ApiClient>
255
+ const api = inject(host, ApiCtx); // signal<ApiClient>
242
256
  return () => html`<div>API version: ${() => api().version}</div>`;
243
257
  });
244
258
  ```
@@ -255,7 +269,7 @@ If you're used to server-side rendering for SEO, in Mado this is solved differen
255
269
  // src/pages/product.ts
256
270
  export default page({
257
271
  bake: {
258
- paths: () => api.allProductSlugs(), // build-time fetch
272
+ paths: () => api.allProductSlugs(), // build-time fetch
259
273
  data: ({ slug }) => api.getProduct(slug),
260
274
  revalidate: 3600,
261
275
  },
@@ -264,7 +278,7 @@ export default page({
264
278
  canonical: `/product/${slug}`,
265
279
  og: { title: data.name, image: data.image },
266
280
  }),
267
- view: ({ params }) => html`<x-product data-slug=${params.slug}/>`,
281
+ view: ({ params }) => html`<x-product data-slug=${params.slug} />`,
268
282
  });
269
283
  ```
270
284
 
@@ -288,14 +302,20 @@ import { page, html, resource, each, signal } from "@madojs/mado";
288
302
  export default page({
289
303
  view: () => {
290
304
  const users = resource(() => "/api/users", jsonFetcher<User[]>());
291
-
305
+
292
306
  return html`
293
- ${() => users.loading() ? html`<p>Loading…</p>` : null}
294
- ${() => users.error() ? html`<p>Error: ${users.error()!.message}</p>` : null}
307
+ ${() => (users.loading() ? html`<p>Loading…</p>` : null)}
308
+ ${() =>
309
+ users.error() ? html`<p>Error: ${users.error()!.message}</p>` : null}
295
310
  <ul>
296
- ${() => each(users.data() ?? [], u => u.id, u => html`
297
- <li><a href="/users/${u.id}" data-link>${u.name}</a></li>
298
- `)}
311
+ ${() =>
312
+ each(
313
+ users.data() ?? [],
314
+ (u) => u.id,
315
+ (u) => html`
316
+ <li><a href="/users/${u.id}" data-link>${u.name}</a></li>
317
+ `,
318
+ )}
299
319
  </ul>
300
320
  `;
301
321
  },
@@ -308,7 +328,10 @@ export default page({
308
328
  import { useForm, mutation } from "@madojs/mado";
309
329
 
310
330
  const createUser = mutation<NewUser, User>(
311
- (u) => fetch("/api/users", { method: "POST", body: JSON.stringify(u) }).then(r => r.json()),
331
+ (u) =>
332
+ fetch("/api/users", { method: "POST", body: JSON.stringify(u) }).then((r) =>
333
+ r.json(),
334
+ ),
312
335
  { invalidates: ["/api/users*"] },
313
336
  );
314
337
 
@@ -316,11 +339,13 @@ const createUser = mutation<NewUser, User>(
316
339
  const f = useForm({ name: { required: true } });
317
340
 
318
341
  html`
319
- <form @submit=${f.onSubmit(async (v) => {
320
- await createUser.run(v);
321
- navigate("/users");
322
- })}>
323
- <input name="name" @input=${f.onInput}>
342
+ <form
343
+ @submit=${f.onSubmit(async (v) => {
344
+ await createUser.run(v);
345
+ navigate("/users");
346
+ })}
347
+ >
348
+ <input name="name" @input=${f.onInput} />
324
349
  <button>Create</button>
325
350
  </form>
326
351
  `;
@@ -353,8 +378,8 @@ export default routes({
353
378
  "/app/*": nested({
354
379
  layout: () => import("./layouts/auth-layout.js"),
355
380
  routes: {
356
- "dashboard": () => import("./pages/dashboard.js"),
357
- "users": () => import("./pages/users.js"),
381
+ dashboard: () => import("./pages/dashboard.js"),
382
+ users: () => import("./pages/users.js"),
358
383
  },
359
384
  }),
360
385
  });
@@ -367,7 +392,7 @@ export default routes({
367
392
  export class ApiClient {
368
393
  constructor(private base: string) {}
369
394
  get<T>(path: string): Promise<T> {
370
- return fetch(this.base + path).then(r => r.json());
395
+ return fetch(this.base + path).then((r) => r.json());
371
396
  }
372
397
  }
373
398