@madojs/mado 0.8.0 → 0.9.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/README.md CHANGED
@@ -6,82 +6,95 @@
6
6
  />
7
7
 
8
8
  <p>
9
- <strong>A small native-web SPA framework you can read in an evening.</strong>
9
+ <strong>Build business apps. Keep maintenance boring.</strong>
10
10
  </p>
11
11
 
12
12
  <p>
13
- <code>tsc browser</code> · Zero runtime dependencies · No required bundler
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 small native-web SPA framework you can read in an evening.
20
+ > A calm frontend stack for internal tools, admin panels and business SPA.
21
21
 
22
22
  [![npm](https://img.shields.io/npm/v/@madojs/mado.svg)](https://www.npmjs.com/package/@madojs/mado)
23
23
  [![CI](https://github.com/madojs/mado/actions/workflows/ci.yml/badge.svg)](https://github.com/madojs/mado/actions/workflows/ci.yml)
24
24
  [![Browser Regression](https://github.com/madojs/mado/actions/workflows/browser.yml/badge.svg)](https://github.com/madojs/mado/actions/workflows/browser.yml)
25
25
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
26
26
 
27
- Mado is a thin TypeScript framework on top of the browser platform: Web
28
- Components, signals, tagged-template `html`, a router, resources, forms,
29
- context, persisted state and static prerender. No runtime dependencies, no
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
- Mado (`窓`) means “window” in Japanese: a calm native-web window into an app,
33
- without dragging a whole frontend factory into the room.
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 does not try to replace the browser platform. The browser already gives
36
- us modules, custom elements, attributes, events, forms, CSS, URLs, history,
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
- ```txt
42
- Runtime budget after build:
43
- native ESM graph: ~60 KB raw, ~24 KB gzip across separate modules
44
- bundled/minified full API: ~32 KB raw, ~11 KB gzip, ~10 KB brotli
45
- Runtime dependencies: 0
46
- Required dev dependency: typescript
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
48
51
 
49
- ## Who It Is For
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.
50
60
 
51
- - Backend developers who need admin panels, dashboards or internal tools
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.
61
+ ## Why teams pick Mado
59
62
 
60
- ## Who It Is Not For
63
+ | What matters to you | Best choice |
64
+ |---|---|
65
+ | Largest ecosystem, most hires available | React or Vue |
66
+ | Reusable design-system components across host frameworks | Lit |
67
+ | Maximum rendering performance, JSX workflow | Solid or Svelte 5 |
68
+ | Progressive enhancement of server-rendered pages | htmx + your backend |
69
+ | Full app stack with minimal infrastructure and calm maintenance | **Mado** |
61
70
 
62
- - Beginners learning frontend for the first time. React, Vue and Svelte have
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.
71
+ **Honest tradeoffs:**
68
72
 
69
- ## Why Not Lit, Solid Or htmx?
73
+ - **vs Lit** Lit is better for design systems. Mado is for whole apps:
74
+ router, data, forms and prerender in one package, no assembly required.
75
+ - **vs Solid** — Solid is faster and more mature. It also requires Vite + a
76
+ babel plugin. Mado requires nothing but `tsc`.
77
+ - **vs htmx** — htmx is excellent when your backend owns HTML. Mado is for
78
+ cases where you want a real SPA: local state, optimistic updates, cached
79
+ resources, lazy modules and persisted UI state.
70
80
 
71
- Short honest version:
81
+ ## What you get
72
82
 
73
- - **Lit** is better for design systems and reusable components that must live
74
- inside many host frameworks. Mado is for whole apps: router, data, forms and
75
- SEO tools in one small package.
76
- - **Solid** is faster and more mature. It also expects a JSX transform and a
77
- build pipeline. Mado intentionally works with browser ESM and `tsc`.
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.
83
+ Routing, forms, state, data fetching and prerendering without ecosystem tax:
81
84
 
82
- Mado does not try to win synthetic benchmark marketing. It avoids a Virtual DOM,
83
- uses fine-grained signals and keyed DOM reconciliation, and aims to stay fast
84
- enough for serious admin apps while remaining small and readable.
85
+ - No dependencies to audit, update or break
86
+ - No bundler required to start (`tsc` is enough)
87
+ - Fewer moving parts to debug
88
+ - Compact API surface you can learn in a day
89
+ - Lower long-term cognitive load
90
+
91
+ ```txt
92
+ Runtime budget:
93
+ bundled/minified: ~32 KB raw, ~11 KB gzip, ~10 KB brotli
94
+ native ESM graph: ~60 KB raw, ~24 KB gzip
95
+ Runtime dependencies: 0
96
+ Required dev dependency: typescript
97
+ ```
85
98
 
86
99
  ## Quick Start
87
100
 
@@ -94,8 +107,8 @@ npm install
94
107
  npm run dev
95
108
  ```
96
109
 
97
- Use the admin starter when you want the blessed production shape out of the box:
98
- layouts, guards, auth/API client, dev proxy, forms and a small admin shell.
110
+ The admin starter gives you the blessed production shape: layouts, guards,
111
+ auth/API client, forms and a small admin shell.
99
112
 
100
113
  ```bash
101
114
  npm exec --package @madojs/mado@latest -- mado init dashboard --starter admin
@@ -104,151 +117,56 @@ npm install
104
117
  npm run dev
105
118
  ```
106
119
 
107
- Use the CRUD starter when you want a compact resource/mutation/forms example:
120
+ The CRUD starter is a compact resource/mutation/forms example:
108
121
 
109
122
  ```bash
110
123
  npm exec --package @madojs/mado@latest -- mado init my-app --starter crud
111
124
  ```
112
125
 
113
- ### Try the repository examples
126
+ ### Try the flagship example
114
127
 
115
128
  ```bash
116
129
  git clone https://github.com/madojs/mado.git
117
130
  cd mado
118
131
  npm install
119
132
  npm run build
120
- npm run serve -- basic
133
+ npm run serve -- showcase
121
134
  ```
122
135
 
123
- ### Small component example
136
+ The showcase is a CRM-shaped pressure app with auth, tables, filters, nested
137
+ routes, context services, forms and real data patterns.
124
138
 
125
- ```ts
126
- // src/pages/counter.ts
127
- import { component, css, html, page, signal } from "@madojs/mado";
139
+ ## How it works
128
140
 
129
- component(
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
- ```
141
+ ### Signals — reactive state
145
142
 
146
143
  ```ts
147
- // src/routes.ts
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";
144
+ import { signal, computed, effect } from "@madojs/mado";
220
145
 
221
146
  const count = signal(0);
222
147
  const doubled = computed(() => count() * 2);
223
-
224
148
  effect(() => console.log(count()));
225
149
 
226
- batch(() => {
227
- count.set(1);
228
- count.set(2);
229
- });
230
-
231
- flushSync();
150
+ count.set(1);
232
151
  ```
233
152
 
234
- Signals are getter functions: read with `count()`, write with `count.set(next)`
153
+ Signals are getter functions: read with `count()`, write with `count.set(v)`
235
154
  or `count.update(fn)`.
236
155
 
237
- ### Templates
156
+ ### Templates — tagged template html
238
157
 
239
158
  ```ts
240
- html`<button @click=${fn} ?disabled=${loading} class=${className}>${label}</button>`;
159
+ html`<button @click=${fn} ?disabled=${loading} class=${cls}>${label}</button>`;
241
160
  ```
242
161
 
243
- - Child bindings accept text, nodes, arrays, nested `html```, and `each(...)`.
244
- - `attr=${v}` writes an attribute.
245
- - `@event=${fn}` attaches an event listener.
246
- - `.prop=${v}` writes a DOM property.
247
- - `?attr=${flag}` toggles a boolean attribute.
248
- - Function values, including signals and computed values, are tracked
249
- reactively.
162
+ - `${value}` child content (text, nodes, arrays, nested `html`, `each`)
163
+ - `@event=${fn}` event listener
164
+ - `attr=${v}` attribute
165
+ - `.prop=${v}` DOM property
166
+ - `?attr=${flag}` boolean attribute
167
+ - Functions and signals are tracked reactively
250
168
 
251
- ### Components
169
+ ### Components — Web Components
252
170
 
253
171
  ```ts
254
172
  import { component, css, html } from "@madojs/mado";
@@ -257,55 +175,30 @@ component(
257
175
  "x-card",
258
176
  () => () => html`<section><slot></slot></section>`,
259
177
  {
260
- styles: css`
261
- :host { display: block; }
262
- section { padding: 1rem; border: 1px solid var(--border); }
263
- `,
178
+ styles: css`:host { display: block; padding: 1rem; }`,
264
179
  },
265
180
  );
266
181
  ```
267
182
 
268
- Components are Custom Elements. Shadow DOM is enabled by default. Use
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
183
+ ### Routing file-based-free
288
184
 
289
185
  ```ts
290
186
  import { routes } from "@madojs/mado";
291
187
 
292
- export const manifest = {
188
+ export default routes({
293
189
  "/": () => import("./pages/home.js"),
294
190
  "/users/:id": () => import("./pages/user-detail.js"),
295
191
  "*": () => import("./pages/not-found.js"),
296
- };
297
-
298
- export default routes(manifest);
192
+ });
299
193
  ```
300
194
 
301
- The router provides lazy page loading, nested routes, query params, hover
302
- prefetch, async stale guards, loading delay, View Transitions support and
303
- `dispose()` for tests/dev overlays.
195
+ Lazy loading, nested routes, query params, guards, hover prefetch, scroll
196
+ restoration, error boundary, View Transitions.
304
197
 
305
- ### Data
198
+ ### Data — resource + mutation
306
199
 
307
200
  ```ts
308
- import { invalidate, jsonFetcher, mutation, resource } from "@madojs/mado";
201
+ import { resource, mutation, invalidate, jsonFetcher } from "@madojs/mado";
309
202
 
310
203
  const user = resource(
311
204
  () => `/api/users/${userId()}`,
@@ -316,18 +209,15 @@ const user = resource(
316
209
  const save = mutation(api.saveUser, {
317
210
  invalidates: ["/api/users*"],
318
211
  });
319
-
320
- await save.run(values);
321
- invalidate("/api/users*");
322
212
  ```
323
213
 
324
- `resource()` handles cache, loading/error state, aborts, refresh and optimistic
325
- local `mutate()`. Inside `component()` setup it is lifecycle-aware.
214
+ Cache, loading/error state, abort, refresh, optimistic `mutate()`,
215
+ glob-based invalidation. Lifecycle-aware inside components.
326
216
 
327
- ### Forms
217
+ ### Forms — schema-based validation
328
218
 
329
219
  ```ts
330
- import { html, useForm } from "@madojs/mado";
220
+ import { useForm, html } from "@madojs/mado";
331
221
 
332
222
  const form = useForm({
333
223
  email: { required: true, type: "email" },
@@ -342,39 +232,86 @@ html`
342
232
  `;
343
233
  ```
344
234
 
345
- Validation is schema-based and intentionally close to native HTML constraints:
346
- `required`, `min`, `max`, `pattern`, `type=email/url/number`, plus optional
347
- custom `validate(values)`. Async validators and field arrays are available via
348
- `validateAsync`, `validateField()` and `form.array("items")`.
235
+ HTML-like constraints (`required`, `min`, `max`, `pattern`, `type`), async
236
+ validators, field arrays. Close to the platform, not fighting it.
349
237
 
350
- Only the root import is the stable public API:
238
+ ### Lists keyed reconciliation
351
239
 
352
240
  ```ts
353
- import { html, component, signal } from "@madojs/mado";
241
+ import { each } from "@madojs/mado";
242
+
243
+ html`<ul>${() => each(items(), (item) => item.id, (item) => html`<li>${item.name}</li>`)}</ul>`;
354
244
  ```
355
245
 
356
- Deep imports may exist in the package for tooling and generated files, but they
357
- are internal and can change before v1.
246
+ ### Static prerender SEO without SSR
358
247
 
359
- ## Static HTML Without Hydration
248
+ ```bash
249
+ mado release
250
+ ```
251
+
252
+ Build-time prerender of routes into static HTML with meta tags and JSON-LD.
253
+ No hydration runtime. For dynamic content, see the Cloudflare edge-prerender
254
+ PoC in [`examples/cloudflare`](./examples/cloudflare/).
255
+
256
+ ## Production
360
257
 
361
- Mado intentionally does not ship SSR with hydration. For SEO-oriented pages it
362
- offers `bake`: build-time prerender of finite routes into HTML with meta tags,
363
- JSON-LD and baked data. For very large or changing catalogs, see the
364
- Cloudflare Worker edge-prerender PoC in [`examples/cloudflare`](./examples/cloudflare/).
258
+ ```bash
259
+ mado release # typecheck + build + bundle + bake + copy public -> out/
260
+ mado preview # serve out/ like a static host
261
+ ```
365
262
 
366
- ## Production Bundle
263
+ One command, one artifact (`out/`). Upload anywhere: VPS, Cloudflare Pages,
264
+ any static CDN.
367
265
 
368
- Native ESM is the default development path. For production, use the one-command
369
- release pipeline:
266
+ ## CLI
370
267
 
371
268
  ```bash
372
- mado release
373
- mado preview
269
+ mado init my-app # scaffold new app
270
+ mado init dashboard --starter admin
271
+ mado dev # dev server with hot reload
272
+ mado build # tsc compile
273
+ mado typecheck # type check without emit
274
+ mado test # run test suite
275
+ mado release # full production build
276
+ mado preview # serve production build locally
374
277
  ```
375
278
 
376
- `release` runs typecheck, build, bundle, bake and public asset copy, then writes
377
- the deployable artifact into `out/`. `preview` serves `out/` like a static host.
279
+ ## Documentation
280
+
281
+ - [The Mado way](./docs/en/00-the-mado-way.md) — conventions and principles
282
+ - [Routing](./docs/en/01-routing.md)
283
+ - [Project layout](./docs/en/02-project-layout.md)
284
+ - [Static bake & SEO](./docs/en/03-static-bake.md)
285
+ - [App architecture](./docs/en/10-app-architecture.md)
286
+ - [Layouts](./docs/en/11-layouts.md)
287
+ - [Auth and API](./docs/en/12-auth-and-api.md)
288
+ - [Deployment](./docs/en/13-deployment.md)
289
+ - [Testing](./docs/en/14-testing.md)
290
+ - [Error handling](./docs/en/15-error-handling.md)
291
+ - [For backend developers](./docs/en/06-for-backenders.md)
292
+ - [Why Mado (detailed comparison)](./docs/en/05-why-mado.md)
293
+
294
+ Localized docs: [French](./docs/fr/README.md) · [Ukrainian](./docs/uk/README.md) · [Russian](./docs/ru/README.md)
295
+
296
+ AI-agent entrypoints: [AGENTS.md](./AGENTS.md) · [llms.txt](./llms.txt)
297
+
298
+ ## Examples
299
+
300
+ - [`examples/showcase`](./examples/showcase/) — flagship CRM pressure app
301
+ (auth, tables, filters, forms, nested routes, context services).
302
+ - [`examples/tickets`](./examples/tickets/) — CRUD validation app.
303
+ - [`examples/basic`](./examples/basic/) — minimal API tour.
304
+ - [`examples/cloudflare`](./examples/cloudflare/) — edge prerender PoC.
305
+
306
+ ## Known Limits
307
+
308
+ | Limit | What it means |
309
+ |---|---|
310
+ | No SSR hydration | Use `bake` or edge prerender for SEO. Server rendering is out of scope. |
311
+ | Small ecosystem | No UI-kit or plugin marketplace. You own your components. |
312
+ | Pre-v1 API | Public API is small and intentional, but may change before v1. |
313
+ | Evergreen browsers only | Modern Chrome, Edge, Firefox, Safari. No IE/legacy. |
314
+ | Template IDE support | `html`` highlighting needs lit-plugin or similar. |
378
315
 
379
316
  ## Tests
380
317
 
@@ -385,25 +322,14 @@ npm test
385
322
  npm run test:browser
386
323
  ```
387
324
 
388
- The test suite covers signals, computed values, effects, dynamic dependencies,
389
- the html parser, keyed reconciliation, resources, mutations, forms, router
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. |
325
+ Covers signals, computed, effects, html parser, keyed reconciliation, resources,
326
+ mutations, forms, router isolation, component lifecycle and example smoke tests.
401
327
 
402
328
  ## Contributing
403
329
 
404
- Read [CONTRIBUTING.md](./CONTRIBUTING.md). The short version: bug fixes with
405
- tests, docs improvements, examples and carefully discussed small core changes
406
- are welcome. Runtime dependencies are not.
330
+ Read [CONTRIBUTING.md](./CONTRIBUTING.md). Bug fixes with tests, docs
331
+ improvements, examples and carefully discussed core changes are welcome.
332
+ Runtime dependencies are not.
407
333
 
408
334
  ## License
409
335