@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.
- package/AGENTS.md +81 -4
- package/CHANGELOG.md +202 -1
- package/README.md +184 -242
- package/ROADMAP.md +174 -79
- package/TODO.md +8 -5
- package/dist/src/component.d.ts +2 -12
- package/dist/src/component.js +30 -29
- package/dist/src/component.js.map +1 -1
- package/dist/src/diagnostics.d.ts +0 -4
- package/dist/src/diagnostics.js +1 -0
- package/dist/src/diagnostics.js.map +1 -1
- package/dist/src/forms.js +17 -0
- package/dist/src/forms.js.map +1 -1
- package/dist/src/html/bindings.js +35 -3
- package/dist/src/html/bindings.js.map +1 -1
- package/dist/src/html/parser.js +60 -3
- package/dist/src/html/parser.js.map +1 -1
- package/dist/src/lifecycle.js +18 -0
- package/dist/src/lifecycle.js.map +1 -1
- package/dist/src/persisted.js +43 -9
- package/dist/src/persisted.js.map +1 -1
- package/dist/src/resource.d.ts +13 -6
- package/dist/src/resource.js +83 -16
- package/dist/src/resource.js.map +1 -1
- package/dist/src/router/manifest.d.ts +0 -3
- package/dist/src/router/manifest.js +23 -2
- package/dist/src/router/manifest.js.map +1 -1
- package/dist/src/router/navigation.js +56 -2
- package/dist/src/router/navigation.js.map +1 -1
- package/dist/src/router.d.ts +1 -1
- package/dist/src/router.js +1 -1
- package/dist/src/router.js.map +1 -1
- package/dist/src/signal.d.ts +0 -4
- package/dist/src/signal.js +56 -7
- package/dist/src/signal.js.map +1 -1
- package/docs/en/00-the-mado-way.md +23 -12
- package/docs/en/03-static-bake.md +1 -2
- package/docs/en/05-why-mado.md +78 -68
- package/docs/en/06-for-backenders.md +80 -55
- package/docs/en/07-llm-pitfalls.md +101 -0
- package/docs/en/08-llm-zero-history-test.md +5 -0
- package/docs/en/18-api-freeze-map.md +63 -0
- package/docs/en/19-reactivity-ordering.md +93 -0
- package/docs/en/20-v1-stability.md +83 -0
- package/docs/en/README.md +3 -0
- package/docs/fr/00-the-mado-way.md +25 -13
- package/docs/fr/03-static-bake.md +1 -2
- package/docs/fr/06-for-backenders.md +6 -0
- package/docs/fr/07-llm-pitfalls.md +2 -0
- package/docs/fr/08-llm-zero-history-test.md +5 -0
- package/docs/fr/18-api-freeze-map.md +63 -0
- package/docs/fr/19-reactivity-ordering.md +97 -0
- package/docs/fr/20-v1-stability.md +88 -0
- package/docs/fr/README.md +3 -0
- package/docs/ru/00-the-mado-way.md +24 -11
- package/docs/ru/03-static-bake.md +2 -3
- package/docs/ru/06-for-backenders.md +6 -0
- package/docs/ru/07-llm-pitfalls.md +2 -0
- package/docs/ru/08-llm-zero-history-test.md +5 -0
- package/docs/ru/18-api-freeze-map.md +62 -0
- package/docs/ru/19-reactivity-ordering.md +95 -0
- package/docs/ru/20-v1-stability.md +82 -0
- package/docs/ru/README.md +3 -0
- package/docs/uk/00-the-mado-way.md +3 -1
- package/docs/uk/06-for-backenders.md +5 -0
- package/docs/uk/07-llm-pitfalls.md +2 -0
- package/docs/uk/08-llm-zero-history-test.md +5 -0
- package/docs/uk/18-api-freeze-map.md +61 -0
- package/docs/uk/19-reactivity-ordering.md +95 -0
- package/docs/uk/20-v1-stability.md +83 -0
- package/docs/uk/README.md +3 -0
- package/llms.txt +63 -7
- package/package.json +10 -5
- package/scripts/bake.mjs +0 -1
- package/scripts/bundle.mjs +6 -6
- package/scripts/cli.mjs +17 -0
- package/scripts/llm-zero-history-smoke.mjs +93 -0
- package/scripts/new.mjs +1 -1
- package/scripts/package-smoke.mjs +74 -0
- package/scripts/size-budget.mjs +88 -0
- package/starters/admin/package.json +2 -2
- package/starters/crud/package.json +2 -2
- package/starters/minimal/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,82 +6,107 @@
|
|
|
6
6
|
/>
|
|
7
7
|
|
|
8
8
|
<p>
|
|
9
|
-
<strong>
|
|
9
|
+
<strong>Build business apps. Keep maintenance boring.</strong>
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
12
|
<p>
|
|
13
|
-
|
|
13
|
+
Browser-native · TypeScript-first · Zero runtime dependencies
|
|
14
14
|
</p>
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
# Mado
|
|
19
19
|
|
|
20
|
-
> A
|
|
20
|
+
> A calm frontend stack for internal tools, admin panels and business SPA.
|
|
21
21
|
|
|
22
22
|
[](https://www.npmjs.com/package/@madojs/mado)
|
|
23
23
|
[](https://github.com/madojs/mado/actions/workflows/ci.yml)
|
|
24
24
|
[](https://github.com/madojs/mado/actions/workflows/browser.yml)
|
|
25
25
|
[](./LICENSE)
|
|
26
26
|
|
|
27
|
-
Mado is a
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
required bundler, no hidden build pipeline: `tsc → browser`.
|
|
27
|
+
Mado is a browser-native SPA framework for teams that want routing, forms,
|
|
28
|
+
data fetching and state management — without turning their frontend into an
|
|
29
|
+
infrastructure project.
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
You write TypeScript, run `tsc`, and open the browser. No JSX transform, no
|
|
32
|
+
Vite required, no hidden build pipeline. The entire runtime is readable in an
|
|
33
|
+
evening. When something breaks, you can read the source and fix it.
|
|
34
34
|
|
|
35
|
-
Mado
|
|
36
|
-
|
|
37
|
-
fetch and the DOM. Mado's job is to make those primitives comfortable enough
|
|
38
|
-
for small and serious applications, without taking away your understanding of
|
|
39
|
-
what is happening.
|
|
35
|
+
Mado (`窓`) means "window" in Japanese: a calm window into your app, without
|
|
36
|
+
dragging a whole frontend factory into the room.
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
38
|
+
## When to use Mado
|
|
39
|
+
|
|
40
|
+
- **Admin panels and dashboards** — forms, tables, filters, auth, role guards.
|
|
41
|
+
- **Internal tools and backoffice** — CRUD workflows, settings, billing UI.
|
|
42
|
+
- **Small SaaS frontends** — where long-term maintainability matters more than
|
|
43
|
+
ecosystem size.
|
|
44
|
+
- **Embedded widgets** — where small footprint and independence from host
|
|
45
|
+
frameworks matter.
|
|
46
|
+
|
|
47
|
+
The common thread: apps where **the frontend should not become its own
|
|
48
|
+
infrastructure problem**.
|
|
49
|
+
|
|
50
|
+
## When not to use Mado
|
|
51
|
+
|
|
52
|
+
- **SEO-heavy public sites** that need SSR with hydration.
|
|
53
|
+
- **Large teams optimizing for hiring compatibility** — React/Vue have bigger
|
|
54
|
+
talent pools.
|
|
55
|
+
- **Projects that need a mature UI-kit ecosystem** comparable to React today.
|
|
56
|
+
- **Beginners learning frontend** — React, Vue and Svelte have far larger
|
|
57
|
+
learning resources.
|
|
58
|
+
- **Teams uncomfortable with a pre-v1 framework** — Mado is honest about its
|
|
59
|
+
stage.
|
|
48
60
|
|
|
49
|
-
##
|
|
61
|
+
## What Mado will not build
|
|
50
62
|
|
|
51
|
-
|
|
52
|
-
without learning another build stack first.
|
|
53
|
-
- Frontend developers who like the browser platform and want a compact,
|
|
54
|
-
readable tool instead of a large ecosystem contract.
|
|
55
|
-
- Small teams that value ownership: if something breaks, `src/` is small
|
|
56
|
-
enough to inspect and patch.
|
|
57
|
-
- Landing pages, widgets, embedded tools and CRUD-heavy SPA surfaces where
|
|
58
|
-
predictable code matters more than framework fashion.
|
|
63
|
+
Mado stays useful by saying no. These are intentionally out of scope:
|
|
59
64
|
|
|
60
|
-
|
|
65
|
+
- SSR with hydration. Use `bake` or edge prerender for SEO-oriented static
|
|
66
|
+
output.
|
|
67
|
+
- A template compiler, JSX transform, or VDOM compatibility layer.
|
|
68
|
+
- A separate store library. Use `signal()`, `computed()` and `resource()`.
|
|
69
|
+
- Suspense primitives or a router plugin system.
|
|
70
|
+
- Built-in i18n, animation, or virtual-scroll primitives.
|
|
71
|
+
- Non-evergreen browser support. The baseline is modern evergreen browsers with
|
|
72
|
+
Baseline 2023 platform features.
|
|
61
73
|
|
|
62
|
-
|
|
63
|
-
far larger learning ecosystems.
|
|
64
|
-
- Teams that need a ready-made UI-kit ecosystem comparable to React.
|
|
65
|
-
- Products that require SSR with hydration as a hard requirement.
|
|
66
|
-
- Projects that need a mature plugin marketplace today.
|
|
67
|
-
- Teams that are uncomfortable using a pre-v1 framework.
|
|
74
|
+
## Why teams pick Mado
|
|
68
75
|
|
|
69
|
-
|
|
76
|
+
| What matters to you | Best choice |
|
|
77
|
+
|---|---|
|
|
78
|
+
| Largest ecosystem, most hires available | React or Vue |
|
|
79
|
+
| Reusable design-system components across host frameworks | Lit |
|
|
80
|
+
| Maximum rendering performance, JSX workflow | Solid or Svelte 5 |
|
|
81
|
+
| Progressive enhancement of server-rendered pages | htmx + your backend |
|
|
82
|
+
| Full app stack with minimal infrastructure and calm maintenance | **Mado** |
|
|
83
|
+
|
|
84
|
+
**Honest tradeoffs:**
|
|
85
|
+
|
|
86
|
+
- **vs Lit** — Lit is better for design systems. Mado is for whole apps:
|
|
87
|
+
router, data, forms and prerender in one package, no assembly required.
|
|
88
|
+
- **vs Solid** — Solid is faster and more mature. It also requires Vite + a
|
|
89
|
+
babel plugin. Mado requires nothing but `tsc`.
|
|
90
|
+
- **vs htmx** — htmx is excellent when your backend owns HTML. Mado is for
|
|
91
|
+
cases where you want a real SPA: local state, optimistic updates, cached
|
|
92
|
+
resources, lazy modules and persisted UI state.
|
|
93
|
+
|
|
94
|
+
## What you get
|
|
70
95
|
|
|
71
|
-
|
|
96
|
+
Routing, forms, state, data fetching and prerendering — without ecosystem tax:
|
|
72
97
|
|
|
73
|
-
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
- **htmx** is excellent when your backend wants to own HTML fragments. Mado is
|
|
79
|
-
for cases where you still want an SPA: local state, optimistic updates,
|
|
80
|
-
cached resources, query params, lazy modules and persisted UI state.
|
|
98
|
+
- No runtime dependencies to audit, update or break
|
|
99
|
+
- No bundler required to start (`tsc` is enough)
|
|
100
|
+
- Fewer moving parts to debug
|
|
101
|
+
- Compact API surface you can learn in a day
|
|
102
|
+
- Lower long-term cognitive load
|
|
81
103
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
104
|
+
```txt
|
|
105
|
+
Runtime budget:
|
|
106
|
+
enforced in CI with npm run size
|
|
107
|
+
Runtime dependencies: 0
|
|
108
|
+
Required dev dependencies: typescript, esbuild, linkedom
|
|
109
|
+
```
|
|
85
110
|
|
|
86
111
|
## Quick Start
|
|
87
112
|
|
|
@@ -94,8 +119,8 @@ npm install
|
|
|
94
119
|
npm run dev
|
|
95
120
|
```
|
|
96
121
|
|
|
97
|
-
|
|
98
|
-
|
|
122
|
+
The admin starter gives you the blessed production shape: layouts, guards,
|
|
123
|
+
auth/API client, forms and a small admin shell.
|
|
99
124
|
|
|
100
125
|
```bash
|
|
101
126
|
npm exec --package @madojs/mado@latest -- mado init dashboard --starter admin
|
|
@@ -104,151 +129,56 @@ npm install
|
|
|
104
129
|
npm run dev
|
|
105
130
|
```
|
|
106
131
|
|
|
107
|
-
|
|
132
|
+
The CRUD starter is a compact resource/mutation/forms example:
|
|
108
133
|
|
|
109
134
|
```bash
|
|
110
135
|
npm exec --package @madojs/mado@latest -- mado init my-app --starter crud
|
|
111
136
|
```
|
|
112
137
|
|
|
113
|
-
### Try the
|
|
138
|
+
### Try the flagship example
|
|
114
139
|
|
|
115
140
|
```bash
|
|
116
141
|
git clone https://github.com/madojs/mado.git
|
|
117
142
|
cd mado
|
|
118
143
|
npm install
|
|
119
144
|
npm run build
|
|
120
|
-
npm run serve --
|
|
145
|
+
npm run serve -- showcase
|
|
121
146
|
```
|
|
122
147
|
|
|
123
|
-
|
|
148
|
+
The showcase is a CRM-shaped pressure app with auth, tables, filters, nested
|
|
149
|
+
routes, context services, forms and real data patterns.
|
|
124
150
|
|
|
125
|
-
|
|
126
|
-
// src/pages/counter.ts
|
|
127
|
-
import { component, css, html, page, signal } from "@madojs/mado";
|
|
151
|
+
## How it works
|
|
128
152
|
|
|
129
|
-
|
|
130
|
-
"x-counter",
|
|
131
|
-
() => {
|
|
132
|
-
const count = signal(0);
|
|
133
|
-
return () => html`
|
|
134
|
-
<button @click=${() => count.update((n) => n + 1)}>${count}</button>
|
|
135
|
-
`;
|
|
136
|
-
},
|
|
137
|
-
{ styles: css`button { padding: .5rem 1rem; }` },
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
export default page({
|
|
141
|
-
title: "Counter",
|
|
142
|
-
view: () => html`<x-counter></x-counter>`,
|
|
143
|
-
});
|
|
144
|
-
```
|
|
153
|
+
### Signals — reactive state
|
|
145
154
|
|
|
146
155
|
```ts
|
|
147
|
-
|
|
148
|
-
import { routes } from "@madojs/mado";
|
|
149
|
-
|
|
150
|
-
export const manifest = {
|
|
151
|
-
"/": () => import("./pages/counter.js"),
|
|
152
|
-
"*": () => import("./pages/not-found.js"),
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
export default routes(manifest);
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
The developer convenience CLI is available as `mado`:
|
|
159
|
-
|
|
160
|
-
```bash
|
|
161
|
-
mado init my-app
|
|
162
|
-
mado init dashboard --starter admin
|
|
163
|
-
mado init my-app --starter crud
|
|
164
|
-
mado dev
|
|
165
|
-
mado build
|
|
166
|
-
mado typecheck
|
|
167
|
-
mado test
|
|
168
|
-
mado release
|
|
169
|
-
mado preview
|
|
170
|
-
mado serve basic
|
|
171
|
-
mado dev showcase
|
|
172
|
-
mado examples
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
## Documentation
|
|
176
|
-
|
|
177
|
-
- [Language index](./docs/README.md)
|
|
178
|
-
- [English docs](./docs/en/README.md)
|
|
179
|
-
- [Russian docs](./docs/ru/README.md)
|
|
180
|
-
- [Documentation française](./docs/fr/README.md)
|
|
181
|
-
- [Ukrainian docs](./docs/uk/README.md)
|
|
182
|
-
|
|
183
|
-
Core topics:
|
|
184
|
-
|
|
185
|
-
- [The Mado way](./docs/en/00-the-mado-way.md)
|
|
186
|
-
- [Routing](./docs/en/01-routing.md)
|
|
187
|
-
- [Project layout](./docs/en/02-project-layout.md)
|
|
188
|
-
- [Static bake & SEO](./docs/en/03-static-bake.md)
|
|
189
|
-
- [IDE setup](./docs/en/04-ide-setup.md)
|
|
190
|
-
- [Why Mado](./docs/en/05-why-mado.md)
|
|
191
|
-
- [For backenders](./docs/en/06-for-backenders.md)
|
|
192
|
-
- [LLM pitfalls](./docs/en/07-llm-pitfalls.md)
|
|
193
|
-
- [Shadow DOM vs Light DOM](./docs/en/09-shadow-vs-light-dom.md)
|
|
194
|
-
- [App architecture](./docs/en/10-app-architecture.md)
|
|
195
|
-
- [Layouts](./docs/en/11-layouts.md)
|
|
196
|
-
- [Auth and API](./docs/en/12-auth-and-api.md)
|
|
197
|
-
- [Deployment](./docs/en/13-deployment.md)
|
|
198
|
-
- [Testing](./docs/en/14-testing.md)
|
|
199
|
-
- [Error handling](./docs/en/15-error-handling.md)
|
|
200
|
-
- [Bake cookbook](./docs/en/16-bake-cookbook.md)
|
|
201
|
-
|
|
202
|
-
AI-agent entrypoints:
|
|
203
|
-
|
|
204
|
-
- [AGENTS.md](./AGENTS.md)
|
|
205
|
-
- [llms.txt](./llms.txt)
|
|
206
|
-
|
|
207
|
-
## Examples
|
|
208
|
-
|
|
209
|
-
- [`examples/basic`](./examples/basic/) — minimal API tour.
|
|
210
|
-
- [`examples/tickets`](./examples/tickets/) — LLM zero-history CRUD validation.
|
|
211
|
-
- [`examples/showcase`](./examples/showcase/) — flagship SaaS CRM pressure app.
|
|
212
|
-
- [`examples/cloudflare`](./examples/cloudflare/) — edge prerender / deployment PoC.
|
|
213
|
-
|
|
214
|
-
## Core API
|
|
215
|
-
|
|
216
|
-
### Signals
|
|
217
|
-
|
|
218
|
-
```ts
|
|
219
|
-
import { batch, computed, effect, flushSync, signal } from "@madojs/mado";
|
|
156
|
+
import { signal, computed, effect } from "@madojs/mado";
|
|
220
157
|
|
|
221
158
|
const count = signal(0);
|
|
222
159
|
const doubled = computed(() => count() * 2);
|
|
223
|
-
|
|
224
160
|
effect(() => console.log(count()));
|
|
225
161
|
|
|
226
|
-
|
|
227
|
-
count.set(1);
|
|
228
|
-
count.set(2);
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
flushSync();
|
|
162
|
+
count.set(1);
|
|
232
163
|
```
|
|
233
164
|
|
|
234
|
-
Signals are getter functions: read with `count()`, write with `count.set(
|
|
165
|
+
Signals are getter functions: read with `count()`, write with `count.set(v)`
|
|
235
166
|
or `count.update(fn)`.
|
|
236
167
|
|
|
237
|
-
### Templates
|
|
168
|
+
### Templates — tagged template html
|
|
238
169
|
|
|
239
170
|
```ts
|
|
240
|
-
html`<button @click=${fn} ?disabled=${loading} class=${
|
|
171
|
+
html`<button @click=${fn} ?disabled=${loading} class=${cls}>${label}</button>`;
|
|
241
172
|
```
|
|
242
173
|
|
|
243
|
-
-
|
|
244
|
-
-
|
|
245
|
-
-
|
|
246
|
-
- `.prop=${v}`
|
|
247
|
-
- `?attr=${flag}`
|
|
248
|
-
-
|
|
249
|
-
reactively.
|
|
174
|
+
- `${value}` — child content (text, nodes, arrays, nested `html`, `each`)
|
|
175
|
+
- `@event=${fn}` — event listener
|
|
176
|
+
- `attr=${v}` — attribute
|
|
177
|
+
- `.prop=${v}` — DOM property
|
|
178
|
+
- `?attr=${flag}` — boolean attribute
|
|
179
|
+
- Functions and signals are tracked reactively
|
|
250
180
|
|
|
251
|
-
### Components
|
|
181
|
+
### Components — Web Components
|
|
252
182
|
|
|
253
183
|
```ts
|
|
254
184
|
import { component, css, html } from "@madojs/mado";
|
|
@@ -257,55 +187,30 @@ component(
|
|
|
257
187
|
"x-card",
|
|
258
188
|
() => () => html`<section><slot></slot></section>`,
|
|
259
189
|
{
|
|
260
|
-
styles: css
|
|
261
|
-
:host { display: block; }
|
|
262
|
-
section { padding: 1rem; border: 1px solid var(--border); }
|
|
263
|
-
`,
|
|
190
|
+
styles: css`:host { display: block; padding: 1rem; }`,
|
|
264
191
|
},
|
|
265
192
|
);
|
|
266
193
|
```
|
|
267
194
|
|
|
268
|
-
|
|
269
|
-
`{ shadow: false }` for app shells and admin layouts that should inherit global
|
|
270
|
-
utility classes.
|
|
271
|
-
|
|
272
|
-
### Lists
|
|
273
|
-
|
|
274
|
-
```ts
|
|
275
|
-
import { each } from "@madojs/mado";
|
|
276
|
-
|
|
277
|
-
html`
|
|
278
|
-
<ul>
|
|
279
|
-
${() => each(items(), (item) => item.id, (item) => html`<li>${item.name}</li>`)}
|
|
280
|
-
</ul>
|
|
281
|
-
`;
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
`each()` performs keyed reconciliation and reuses DOM nodes across reorder,
|
|
285
|
-
insert and delete operations.
|
|
286
|
-
|
|
287
|
-
### Routing
|
|
195
|
+
### Routing — file-based-free
|
|
288
196
|
|
|
289
197
|
```ts
|
|
290
198
|
import { routes } from "@madojs/mado";
|
|
291
199
|
|
|
292
|
-
export
|
|
200
|
+
export default routes({
|
|
293
201
|
"/": () => import("./pages/home.js"),
|
|
294
202
|
"/users/:id": () => import("./pages/user-detail.js"),
|
|
295
203
|
"*": () => import("./pages/not-found.js"),
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
export default routes(manifest);
|
|
204
|
+
});
|
|
299
205
|
```
|
|
300
206
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
`dispose()` for tests/dev overlays.
|
|
207
|
+
Lazy loading, nested routes, query params, guards, hover prefetch, scroll
|
|
208
|
+
restoration, error boundary, View Transitions.
|
|
304
209
|
|
|
305
|
-
### Data
|
|
210
|
+
### Data — resource + mutation
|
|
306
211
|
|
|
307
212
|
```ts
|
|
308
|
-
import {
|
|
213
|
+
import { resource, mutation, invalidate, jsonFetcher } from "@madojs/mado";
|
|
309
214
|
|
|
310
215
|
const user = resource(
|
|
311
216
|
() => `/api/users/${userId()}`,
|
|
@@ -316,18 +221,19 @@ const user = resource(
|
|
|
316
221
|
const save = mutation(api.saveUser, {
|
|
317
222
|
invalidates: ["/api/users*"],
|
|
318
223
|
});
|
|
319
|
-
|
|
320
|
-
await save.run(values);
|
|
321
|
-
invalidate("/api/users*");
|
|
322
224
|
```
|
|
323
225
|
|
|
324
|
-
|
|
325
|
-
|
|
226
|
+
Cache, loading/error state, abort, refresh, optimistic `mutate()`,
|
|
227
|
+
glob-based invalidation. Lifecycle-aware inside components.
|
|
228
|
+
|
|
229
|
+
Resource keys are the cache identity. Use keys that include the endpoint, params
|
|
230
|
+
and data shape; two resources with the same key share cached data and in-flight
|
|
231
|
+
requests.
|
|
326
232
|
|
|
327
|
-
### Forms
|
|
233
|
+
### Forms — schema-based validation
|
|
328
234
|
|
|
329
235
|
```ts
|
|
330
|
-
import {
|
|
236
|
+
import { useForm, html } from "@madojs/mado";
|
|
331
237
|
|
|
332
238
|
const form = useForm({
|
|
333
239
|
email: { required: true, type: "email" },
|
|
@@ -342,39 +248,86 @@ html`
|
|
|
342
248
|
`;
|
|
343
249
|
```
|
|
344
250
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
custom `validate(values)`. Async validators and field arrays are available via
|
|
348
|
-
`validateAsync`, `validateField()` and `form.array("items")`.
|
|
251
|
+
HTML-like constraints (`required`, `min`, `max`, `pattern`, `type`), async
|
|
252
|
+
validators, field arrays. Close to the platform, not fighting it.
|
|
349
253
|
|
|
350
|
-
|
|
254
|
+
### Lists — keyed reconciliation
|
|
351
255
|
|
|
352
256
|
```ts
|
|
353
|
-
import {
|
|
257
|
+
import { each } from "@madojs/mado";
|
|
258
|
+
|
|
259
|
+
html`<ul>${() => each(items(), (item) => item.id, (item) => html`<li>${item.name}</li>`)}</ul>`;
|
|
354
260
|
```
|
|
355
261
|
|
|
356
|
-
|
|
357
|
-
are internal and can change before v1.
|
|
262
|
+
### Static prerender — SEO without SSR
|
|
358
263
|
|
|
359
|
-
|
|
264
|
+
```bash
|
|
265
|
+
mado release
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Build-time prerender of routes into static HTML with meta tags and JSON-LD.
|
|
269
|
+
No hydration runtime. For dynamic content, see the Cloudflare edge-prerender
|
|
270
|
+
PoC in [`examples/cloudflare`](./examples/cloudflare/).
|
|
360
271
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
272
|
+
## Production
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
mado release # typecheck + build + bundle + bake + copy public -> out/
|
|
276
|
+
mado preview # serve out/ like a static host
|
|
277
|
+
```
|
|
365
278
|
|
|
366
|
-
|
|
279
|
+
One command, one artifact (`out/`). Upload anywhere: VPS, Cloudflare Pages,
|
|
280
|
+
any static CDN.
|
|
367
281
|
|
|
368
|
-
|
|
369
|
-
release pipeline:
|
|
282
|
+
## CLI
|
|
370
283
|
|
|
371
284
|
```bash
|
|
372
|
-
mado
|
|
373
|
-
mado
|
|
285
|
+
mado init my-app # scaffold new app
|
|
286
|
+
mado init dashboard --starter admin
|
|
287
|
+
mado dev # dev server with hot reload
|
|
288
|
+
mado build # tsc compile
|
|
289
|
+
mado typecheck # type check without emit
|
|
290
|
+
mado test # run test suite
|
|
291
|
+
mado release # full production build
|
|
292
|
+
mado preview # serve production build locally
|
|
374
293
|
```
|
|
375
294
|
|
|
376
|
-
|
|
377
|
-
|
|
295
|
+
## Documentation
|
|
296
|
+
|
|
297
|
+
- [The Mado way](./docs/en/00-the-mado-way.md) — conventions and principles
|
|
298
|
+
- [Routing](./docs/en/01-routing.md)
|
|
299
|
+
- [Project layout](./docs/en/02-project-layout.md)
|
|
300
|
+
- [Static bake & SEO](./docs/en/03-static-bake.md)
|
|
301
|
+
- [App architecture](./docs/en/10-app-architecture.md)
|
|
302
|
+
- [Layouts](./docs/en/11-layouts.md)
|
|
303
|
+
- [Auth and API](./docs/en/12-auth-and-api.md)
|
|
304
|
+
- [Deployment](./docs/en/13-deployment.md)
|
|
305
|
+
- [Testing](./docs/en/14-testing.md)
|
|
306
|
+
- [Error handling](./docs/en/15-error-handling.md)
|
|
307
|
+
- [For backend developers](./docs/en/06-for-backenders.md)
|
|
308
|
+
- [Why Mado (detailed comparison)](./docs/en/05-why-mado.md)
|
|
309
|
+
|
|
310
|
+
Localized docs: [French](./docs/fr/README.md) · [Ukrainian](./docs/uk/README.md) · [Russian](./docs/ru/README.md)
|
|
311
|
+
|
|
312
|
+
AI-agent entrypoints: [AGENTS.md](./AGENTS.md) · [llms.txt](./llms.txt)
|
|
313
|
+
|
|
314
|
+
## Examples
|
|
315
|
+
|
|
316
|
+
- [`examples/showcase`](./examples/showcase/) — flagship CRM pressure app
|
|
317
|
+
(auth, tables, filters, forms, nested routes, context services).
|
|
318
|
+
- [`examples/tickets`](./examples/tickets/) — CRUD validation app.
|
|
319
|
+
- [`examples/basic`](./examples/basic/) — minimal API tour.
|
|
320
|
+
- [`examples/cloudflare`](./examples/cloudflare/) — edge prerender PoC.
|
|
321
|
+
|
|
322
|
+
## Known Limits
|
|
323
|
+
|
|
324
|
+
| Limit | What it means |
|
|
325
|
+
|---|---|
|
|
326
|
+
| No SSR hydration | Use `bake` or edge prerender for SEO. Server rendering is out of scope. |
|
|
327
|
+
| Small ecosystem | No UI-kit or plugin marketplace. You own your components. |
|
|
328
|
+
| Pre-v1 API | Public API is small and intentional, but may change before v1. |
|
|
329
|
+
| Evergreen browsers only | Modern Chrome, Edge, Firefox, Safari. No IE/legacy. |
|
|
330
|
+
| Template IDE support | `html`` highlighting needs lit-plugin or similar. |
|
|
378
331
|
|
|
379
332
|
## Tests
|
|
380
333
|
|
|
@@ -385,25 +338,14 @@ npm test
|
|
|
385
338
|
npm run test:browser
|
|
386
339
|
```
|
|
387
340
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
isolation, component lifecycle and example smoke tests.
|
|
391
|
-
|
|
392
|
-
## Known Limits
|
|
393
|
-
|
|
394
|
-
| Limit | Meaning |
|
|
395
|
-
|---|---|
|
|
396
|
-
| No SSR hydration | Use `bake` or edge prerender for SEO. Per-user server rendering is intentionally out of scope for now. |
|
|
397
|
-
| Small ecosystem | No plugin marketplace or UI-kit ecosystem comparable to React. |
|
|
398
|
-
| Template IDE support needs plugins | `html`` syntax highlighting/type tooling usually needs lit-plugin or similar tooling. |
|
|
399
|
-
| Evergreen browsers | Targets modern Chrome/Edge/Firefox/Safari. Legacy browsers are out of scope. |
|
|
400
|
-
| Pre-v1 API | Public API is intentionally small, but v0.x may still change before v1. |
|
|
341
|
+
Covers signals, computed, effects, html parser, keyed reconciliation, resources,
|
|
342
|
+
mutations, forms, router isolation, component lifecycle and example smoke tests.
|
|
401
343
|
|
|
402
344
|
## Contributing
|
|
403
345
|
|
|
404
|
-
Read [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
405
|
-
|
|
406
|
-
|
|
346
|
+
Read [CONTRIBUTING.md](./CONTRIBUTING.md). Bug fixes with tests, docs
|
|
347
|
+
improvements, examples and carefully discussed core changes are welcome.
|
|
348
|
+
Runtime dependencies are not.
|
|
407
349
|
|
|
408
350
|
## License
|
|
409
351
|
|