@madojs/mado 0.5.1 → 0.6.1
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 +26 -0
- package/CHANGELOG.md +265 -0
- package/MADO_V1_PLAN.md +179 -0
- package/README.md +31 -13
- package/ROADMAP.md +28 -7
- package/TODO.md +72 -0
- package/dist/src/forms.d.ts +37 -4
- package/dist/src/forms.js +331 -57
- package/dist/src/forms.js.map +1 -1
- package/dist/src/html/bindings.d.ts +41 -0
- package/dist/src/html/bindings.js +163 -6
- package/dist/src/html/bindings.js.map +1 -1
- package/dist/src/html.d.ts +2 -0
- package/dist/src/html.js +1 -0
- package/dist/src/html.js.map +1 -1
- package/dist/src/index.d.ts +6 -6
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/page.d.ts +56 -0
- package/dist/src/page.js +17 -0
- package/dist/src/page.js.map +1 -1
- package/dist/src/resource.js +11 -0
- package/dist/src/resource.js.map +1 -1
- package/dist/src/router/manifest.d.ts +16 -1
- package/dist/src/router/manifest.js +210 -40
- package/dist/src/router/manifest.js.map +1 -1
- package/dist/src/router/match.d.ts +7 -2
- package/dist/src/router/match.js +14 -4
- package/dist/src/router/match.js.map +1 -1
- package/dist/src/router/navigation.d.ts +10 -0
- package/dist/src/router/navigation.js +71 -3
- package/dist/src/router/navigation.js.map +1 -1
- package/dist/src/signal.d.ts +15 -1
- package/dist/src/signal.js +112 -16
- package/dist/src/signal.js.map +1 -1
- package/docs/en/02-project-layout.md +99 -40
- package/docs/en/10-app-architecture.md +141 -0
- package/docs/en/11-layouts.md +115 -0
- package/docs/en/12-auth-and-api.md +217 -0
- package/docs/en/13-deployment.md +192 -0
- package/docs/en/14-testing.md +82 -0
- package/docs/en/15-error-handling.md +100 -0
- package/docs/en/16-bake-cookbook.md +93 -0
- package/docs/en/README.md +7 -0
- package/docs/fr/10-app-architecture.md +61 -0
- package/docs/fr/11-layouts.md +35 -0
- package/docs/fr/12-auth-and-api.md +35 -0
- package/docs/fr/13-deployment.md +39 -0
- package/docs/fr/14-testing.md +41 -0
- package/docs/fr/15-error-handling.md +50 -0
- package/docs/fr/16-bake-cookbook.md +35 -0
- package/docs/fr/README.md +7 -0
- package/docs/ru/10-app-architecture.md +100 -0
- package/docs/ru/11-layouts.md +47 -0
- package/docs/ru/12-auth-and-api.md +53 -0
- package/docs/ru/13-deployment.md +60 -0
- package/docs/ru/14-testing.md +50 -0
- package/docs/ru/15-error-handling.md +56 -0
- package/docs/ru/16-bake-cookbook.md +55 -0
- package/docs/ru/README.md +7 -0
- package/docs/uk/10-app-architecture.md +56 -0
- package/docs/uk/11-layouts.md +34 -0
- package/docs/uk/12-auth-and-api.md +34 -0
- package/docs/uk/13-deployment.md +39 -0
- package/docs/uk/14-testing.md +34 -0
- package/docs/uk/15-error-handling.md +32 -0
- package/docs/uk/16-bake-cookbook.md +36 -0
- package/docs/uk/README.md +7 -0
- package/llms.txt +9 -1
- package/package.json +3 -1
- package/scripts/_config.mjs +224 -0
- package/scripts/bake.mjs +266 -121
- package/scripts/bundle.mjs +133 -67
- package/scripts/cli.mjs +195 -27
- package/scripts/preview.mjs +125 -21
- package/server/serve.mjs +161 -10
- package/starters/admin/README.md +63 -0
- package/starters/admin/index.html +28 -0
- package/starters/admin/mado.config.json +22 -0
- package/starters/admin/package.json +24 -0
- package/starters/admin/public/favicon.svg +4 -0
- package/starters/admin/src/components/x-button.ts +55 -0
- package/starters/admin/src/components/x-input.ts +74 -0
- package/starters/admin/src/layouts/app.ts +101 -0
- package/starters/admin/src/layouts/auth.ts +41 -0
- package/starters/admin/src/lib/api.ts +133 -0
- package/starters/admin/src/lib/auth.ts +83 -0
- package/starters/admin/src/main.ts +15 -0
- package/starters/admin/src/pages/admin/dashboard.ts +48 -0
- package/starters/admin/src/pages/admin/order-detail.ts +80 -0
- package/starters/admin/src/pages/admin/orders.ts +117 -0
- package/starters/admin/src/pages/home.ts +34 -0
- package/starters/admin/src/pages/login.ts +70 -0
- package/starters/admin/src/pages/not-found.ts +12 -0
- package/starters/admin/src/routes.ts +40 -0
- package/starters/admin/src/styles/global.ts +86 -0
- package/starters/admin/tsconfig.json +15 -0
- package/starters/crud/index.html +12 -4
- package/starters/crud/mado.config.json +20 -0
- package/starters/crud/package.json +9 -3
- package/starters/crud/src/pages/home.ts +16 -0
- package/starters/crud/src/routes.ts +4 -2
- package/starters/minimal/index.html +12 -4
- package/starters/minimal/mado.config.json +20 -0
- package/starters/minimal/package.json +9 -3
- package/starters/minimal/src/pages/home.ts +17 -0
- package/starters/minimal/src/routes.ts +4 -2
package/AGENTS.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
> This file is read by AI agents in IDEs (Cursor, Cline, Copilot, Continue, etc.).
|
|
4
4
|
> Goal: prevent them from generating React-like code where Mado should be used.
|
|
5
|
+
>
|
|
6
|
+
> The v0.6 product-surface push is archived in
|
|
7
|
+
> [`MADO_V1_PLAN.md`](./MADO_V1_PLAN.md). New work should follow `ROADMAP.md`
|
|
8
|
+
> / `TODO.md` unless the user explicitly resumes that tracker.
|
|
5
9
|
|
|
6
10
|
## Project at a glance
|
|
7
11
|
|
|
@@ -289,6 +293,25 @@ src/
|
|
|
289
293
|
└── lib/ ← API client, contexts, pure logic
|
|
290
294
|
```
|
|
291
295
|
|
|
296
|
+
## App architecture for LLM
|
|
297
|
+
|
|
298
|
+
When generating an app, prefer the blessed production shape from
|
|
299
|
+
`docs/en/10-app-architecture.md` and the `starters/admin/` example:
|
|
300
|
+
|
|
301
|
+
- `src/main.ts` mounts `routesApi.view` and imports only global styles,
|
|
302
|
+
providers, and tiny shared components.
|
|
303
|
+
- `src/routes.ts` exports both `manifest` and `default routes(manifest, ...)`.
|
|
304
|
+
- Put route wrappers in `src/layouts/` via `layout()`, not ad-hoc shell logic
|
|
305
|
+
inside every page.
|
|
306
|
+
- Put backend access in `src/lib/api.ts` and auth/session logic in
|
|
307
|
+
`src/lib/auth.ts`; guards call auth helpers, pages call API helpers.
|
|
308
|
+
- Put one page per file under `src/pages/`; a page imports the feature
|
|
309
|
+
components it renders.
|
|
310
|
+
- Use `resource()` for reads, `mutation(..., { invalidates })` for writes,
|
|
311
|
+
and `useForm()` for form state/validation.
|
|
312
|
+
- Use `mado release` as the production path. `out/` is the only deploy
|
|
313
|
+
artifact; `dist/` is internal build output.
|
|
314
|
+
|
|
292
315
|
## Where to find specific answers
|
|
293
316
|
|
|
294
317
|
| Question | File |
|
|
@@ -298,6 +321,9 @@ src/
|
|
|
298
321
|
| How does the router work? | `src/router.ts` (~530 lines) |
|
|
299
322
|
| How does resource + cache work? | `src/resource.ts` (297 lines) |
|
|
300
323
|
| How do forms work? | `src/forms.ts` (212 lines) |
|
|
324
|
+
| How should an app be structured? | `docs/en/10-app-architecture.md` |
|
|
325
|
+
| How should errors be handled? | `docs/en/15-error-handling.md` |
|
|
326
|
+
| How should bake be used? | `docs/en/16-bake-cookbook.md` |
|
|
301
327
|
| When something goes wrong | `docs/en/07-llm-pitfalls.md` |
|
|
302
328
|
|
|
303
329
|
## Before committing
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,270 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
Nothing yet.
|
|
6
|
+
|
|
7
|
+
## 0.6.1
|
|
8
|
+
|
|
9
|
+
Starter & release-pipeline hardening pass. No public API breaks.
|
|
10
|
+
Identified from a lab pressure-test on `/admin/lab` plus a deep audit of the
|
|
11
|
+
starter / bundle / bake / dev-server contour. All fixes verified by
|
|
12
|
+
regression tests added in this release.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- **Starters**: every `index.html` in `starters/{admin,crud,minimal}/` now
|
|
16
|
+
uses root-absolute paths in the importmap and entry `<script>` tag
|
|
17
|
+
(`/node_modules/@madojs/mado/...`, `/dist/main.js`). Relative paths
|
|
18
|
+
(`./node_modules/...`, `./dist/main.js`) broke hard-refresh of any nested
|
|
19
|
+
route (`/admin/orders/42` → browser fetched
|
|
20
|
+
`/admin/orders/dist/main.js` → 404 → blank page). Inline comments in each
|
|
21
|
+
file explain the trap so it does not get reverted.
|
|
22
|
+
- **Starters/admin**: `pages/admin/order-detail.ts` now uses `each(items,
|
|
23
|
+
key, render)` instead of `o.items.map(...)`, matching `llms.txt` rule #3
|
|
24
|
+
and the framework's own pitfalls documentation.
|
|
25
|
+
- **`scripts/bundle.mjs`**: cleans stale hashed assets before every build.
|
|
26
|
+
Previously each `mado bundle` / `mado release` left old `main-<hash>.js`
|
|
27
|
+
and `chunk-<hash>.js` in `out/assets/`; the rewriter then emitted
|
|
28
|
+
`<link rel="modulepreload">` for every leftover `.js` it found, so
|
|
29
|
+
production HTML shipped dead-code preloads without SRI. In app-mode the
|
|
30
|
+
whole assets directory is wiped; in repo-mode only recognisable hashed
|
|
31
|
+
files are removed so unrelated repo artifacts stay put.
|
|
32
|
+
- **`src/router/manifest.ts`**: opens a fresh component lifecycle scope
|
|
33
|
+
around every `page.view()` / layout `view()` call and disposes the
|
|
34
|
+
previous one on navigation (and on `router.dispose()`). `resource()`,
|
|
35
|
+
`effect()` and `persisted()` created inside `page.view()` now register
|
|
36
|
+
cleanup with that scope automatically — no more
|
|
37
|
+
`[mado:resource-outside-lifecycle]` warnings on the framework's own
|
|
38
|
+
canonical examples, and no more invalidator-subscription leaks across
|
|
39
|
+
route changes.
|
|
40
|
+
- **`src/resource.ts`**: guards against stale responses overwriting fresh
|
|
41
|
+
data on rapid key changes. The previous `AbortController` defence worked
|
|
42
|
+
only if the user-supplied fetcher honored `AbortSignal` — for fetchers
|
|
43
|
+
that ignore cancellation, a slow stale resolution for an old key could
|
|
44
|
+
win over a fast fresh one. Both then/catch branches now also check
|
|
45
|
+
`if (key !== lastKey) return`.
|
|
46
|
+
- **`server/serve.mjs`**: falls back to `./public/*` when a file is not
|
|
47
|
+
found at the project root, mirroring what `mado release` does to `out/`.
|
|
48
|
+
`favicon.svg`, `robots.txt`, `og-image.png` etc. no longer 404 in dev.
|
|
49
|
+
- **`server/serve.mjs`**: prints an actionable hint on `EPERM`/`EACCES`
|
|
50
|
+
pointing at `mado dev --host 127.0.0.1` (the default host changed from
|
|
51
|
+
the implicit `0.0.0.0` to `localhost`, which is friendlier in sandboxed
|
|
52
|
+
environments).
|
|
53
|
+
- **`scripts/preview.mjs`**: serves prerendered HTML from `<out>/baked/`
|
|
54
|
+
with priority over the SPA shell. Previously `mado preview` only looked
|
|
55
|
+
at `out/` and never saw bake's output, so prerendered routes returned
|
|
56
|
+
the empty SPA shell — looking like a "blank page" bug even when bake
|
|
57
|
+
had succeeded.
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
- **`mado dev` / `mado serve` flag pass-through**: `cli.mjs` now splits
|
|
61
|
+
positional arguments from flags via `splitDevArgs()`, so calls like
|
|
62
|
+
`mado dev --host 127.0.0.1`, `mado dev showcase --port 6000` and
|
|
63
|
+
`mado dev -- --host 0.0.0.0` all work. Previously the CLI mistook the
|
|
64
|
+
flag for an example name and exited with `unknown example`.
|
|
65
|
+
- **`server/serve.mjs`**: tiny argv parser supporting `--host`, `--port`
|
|
66
|
+
and `--host=value` forms; HOST and PORT also fall back to environment
|
|
67
|
+
variables and `mado.config.json` (`dev.host`, `dev.port`).
|
|
68
|
+
- **`scripts/preview.mjs`**: same `--host` / `--port` flags as the dev
|
|
69
|
+
server, plus a startup banner showing `url:` / `out:` / `baked:` so it
|
|
70
|
+
is obvious which directories preview is serving from.
|
|
71
|
+
- **`scripts/bake.mjs`**: fails loudly when the manifest exists but no
|
|
72
|
+
page declares `bake: { paths, data }`. The previous behaviour produced
|
|
73
|
+
`0 pages + sitemap.xml` silently with exit code 0, making `mado
|
|
74
|
+
release` look successful while shipping only the SPA shell with no
|
|
75
|
+
SEO-friendly HTML. The new warning prints the skipped routes, a
|
|
76
|
+
worked example bake snippet, and exits non-zero. Override with
|
|
77
|
+
`MADO_BAKE_ALLOW_EMPTY=1` for intentional SPA-only deploys.
|
|
78
|
+
- **`scripts/bake.mjs`**: clearer "missing dev dep" errors — when
|
|
79
|
+
`linkedom` or `esbuild` is missing the message now tells the user
|
|
80
|
+
exactly which packages to `npm i -D`.
|
|
81
|
+
- **Starter landing pages**: `home.ts` in all three starters now declares
|
|
82
|
+
`bake: { paths: () => [{}], data: () => ({}) }` and a `head()` so
|
|
83
|
+
`mado release` actually prerenders the landing page out of the box.
|
|
84
|
+
- **Starter `devDependencies`**: `linkedom` and `esbuild` added to
|
|
85
|
+
`starters/{admin,crud,minimal}/package.json` so `mado release` works
|
|
86
|
+
immediately after `mado init <app>` + `npm install`, without manual
|
|
87
|
+
follow-up installs.
|
|
88
|
+
- **Regression tests** (`test/`):
|
|
89
|
+
- `starter-html-paths.test.mjs` — asserts every starter `index.html`
|
|
90
|
+
uses root-absolute paths in both the importmap and the entry script.
|
|
91
|
+
- `bundle-cleanup.test.mjs` — end-to-end: runs `mado bundle` twice on
|
|
92
|
+
a synthesized temp project (mutating source between runs) and
|
|
93
|
+
asserts there is exactly one `main-<hash>.js` in `out/assets/`
|
|
94
|
+
afterwards.
|
|
95
|
+
- `resource.test.mjs` (2 new cases) — stale-response races: a fetcher
|
|
96
|
+
that ignores `AbortSignal` with key=1 slower than key=2, plus a
|
|
97
|
+
rapid 3-way key thrash where the final key is the slowest fetch.
|
|
98
|
+
Both assert `data()` reflects the latest key, not the fastest
|
|
99
|
+
response.
|
|
100
|
+
|
|
101
|
+
### Changed
|
|
102
|
+
- **`server/serve.mjs`** default host is now `localhost` (was implicitly
|
|
103
|
+
`0.0.0.0`). LAN exposure is opt-in via `mado dev --host 0.0.0.0` or
|
|
104
|
+
`HOST=0.0.0.0`. The startup banner shows both the bound host and a
|
|
105
|
+
click-friendly URL (`localhost` substituted when bound to `0.0.0.0`).
|
|
106
|
+
|
|
107
|
+
### Notes
|
|
108
|
+
- No public API changes; no migrations required. Apps that previously
|
|
109
|
+
worked on a fresh-out-of-the-box `mado init` did so only because
|
|
110
|
+
someone manually fixed the starter's relative paths and dev deps —
|
|
111
|
+
this release closes those gaps so the documented "happy path" actually
|
|
112
|
+
is happy.
|
|
113
|
+
- If you intentionally deploy SPA-only (no prerendered HTML), drop
|
|
114
|
+
`mado bake` from your release pipeline or set
|
|
115
|
+
`MADO_BAKE_ALLOW_EMPTY=1`; otherwise bake will now fail your
|
|
116
|
+
CI with a clear pointer to the missing config.
|
|
117
|
+
- Test count: 137 pass, 0 fail, 3 skipped (Playwright e2e — unchanged).
|
|
118
|
+
|
|
119
|
+
## 0.6.0
|
|
120
|
+
|
|
121
|
+
Product-surface release: app-mode defaults, blessed admin starter, release
|
|
122
|
+
pipeline, core hardening and v1 recipe docs.
|
|
123
|
+
|
|
124
|
+
Phase 1 — Repo-vs-app split:
|
|
125
|
+
|
|
126
|
+
### Added
|
|
127
|
+
- `MADO_V1_PLAN.md` — executable tracker for the v1 push.
|
|
128
|
+
- `scripts/_config.mjs` — single configuration loader (defaults < `mado.config.json`
|
|
129
|
+
< CLI flags). Exports `loadConfig`, `detectContext`, `parseFlags`,
|
|
130
|
+
`resolveProjectPath`. [v1 F1.1]
|
|
131
|
+
- `mado release` command: one-shot `typecheck + build + bundle + bake + copy
|
|
132
|
+
public/ → out/` pipeline so apps have exactly one command to ship. [v1 F1.3]
|
|
133
|
+
- `mado.config.json` shipped in the `minimal` and `crud` starters with the
|
|
134
|
+
default app-mode layout (`src/routes.ts`, `index.html`, `out/`). [v1 F1.4]
|
|
135
|
+
- Tests: `test/config-loader.test.mjs`, `test/bake-cli.test.mjs` (11 + 3
|
|
136
|
+
cases covering context detection, config precedence, flag parsing, bake
|
|
137
|
+
flags, and the no-more-silent-`[object Object]` contract). [v1 F1.6]
|
|
138
|
+
|
|
139
|
+
### Changed
|
|
140
|
+
- `scripts/bake.mjs` now reads configuration from `mado.config.json` and
|
|
141
|
+
accepts `--entry`, `--template`, `--out`, `--base-url` flags. In app-mode
|
|
142
|
+
defaults are `src/routes.ts` + `index.html` + `out/baked/`; the
|
|
143
|
+
`@madojs/mado → src/index.ts` alias is repo-only. [v1 F1.2]
|
|
144
|
+
- `scripts/bake.mjs` no longer renders unsupported values as `[object Object]`;
|
|
145
|
+
it raises a loud, file/route-targeted error with a hint instead. [v1 F1.2]
|
|
146
|
+
- `scripts/cli.mjs` detects repo-vs-app context, advertises `mado release`,
|
|
147
|
+
and ships a redesigned `mado help` that explains the dev / build / release
|
|
148
|
+
/ preview pipeline. [v1 F1.3]
|
|
149
|
+
- Starter `package.json` scripts go through the `mado` CLI exclusively
|
|
150
|
+
(`mado build`, `mado dev`, `mado bundle`, `mado bake`, `mado release`,
|
|
151
|
+
`mado preview`). [v1 F1.4]
|
|
152
|
+
- `docs/en/02-project-layout.md` rewritten around the canonical `src/` /
|
|
153
|
+
`dist/` / `public/` / `out/` model plus a `mado.config.json` one-screen
|
|
154
|
+
reference. [v1 F1.5]
|
|
155
|
+
- `ROADMAP.md`, `TODO.md`, `AGENTS.md` now distinguish the completed
|
|
156
|
+
`MADO_V1_PLAN.md` archive from future roadmap/TODO work. [v1 F0]
|
|
157
|
+
|
|
158
|
+
Phase 2 — One blessed way:
|
|
159
|
+
|
|
160
|
+
### Added
|
|
161
|
+
- `layout()` factory in `src/page.ts` (alias of `nested()`) plus `Guard` and
|
|
162
|
+
`GuardResult` types. Exported from the public API. [v1 F2.1 / F2.3]
|
|
163
|
+
- Route guards: nested groups and individual pages accept `guard: Guard | Guard[]`.
|
|
164
|
+
Verdicts: void (pass), `{ halt: true }`, or `{ redirect, replace? }`. Async-aware
|
|
165
|
+
with a sync fast path; throwing guards are treated as `halt`. [v1 F2.2]
|
|
166
|
+
- New starter `starters/admin/`: nested manifest with `/`, `/login`, `/admin`
|
|
167
|
+
groups; blessed `lib/api.ts` (`createApiClient`, `ApiError`, single-flight
|
|
168
|
+
401-refresh) and `lib/auth.ts` (`accessToken`, `restoreSession`, `requireAuth`,
|
|
169
|
+
`login`, `logout`); `layouts/{app,auth}.ts` with a real admin shell; tiny
|
|
170
|
+
`x-button`/`x-input` design-token components; dashboard + orders + order-detail
|
|
171
|
+
pages; `mado.config.json` with a dev `/api` proxy; `public/favicon.svg`. [v1 F2.4]
|
|
172
|
+
- CLI advertises `mado init <name> --starter admin` and lists it in `mado help`.
|
|
173
|
+
[v1 F2.5]
|
|
174
|
+
- `docs/en/11-layouts.md` — the canonical layout recipe (nested routes) plus
|
|
175
|
+
two acceptable alternatives with caveats. [v1 F2.6]
|
|
176
|
+
- `docs/en/12-auth-and-api.md` — the blessed `api`/`auth` recipes, backend
|
|
177
|
+
contract, and dev-proxy hint. [v1 F2.7]
|
|
178
|
+
- `test/guards-layouts.test.mjs` — 7 cases covering the public `layout()`
|
|
179
|
+
alias, sync pass/halt/redirect, async guards, parent→page guard order, and
|
|
180
|
+
throwing-guard fallback. [v1 F2.8]
|
|
181
|
+
|
|
182
|
+
Phase 3 — Bake first-class + Release pipeline:
|
|
183
|
+
|
|
184
|
+
### Added
|
|
185
|
+
- `mado release` writes `_redirects` (`/* /index.html 200`) and `_headers`
|
|
186
|
+
(immutable for `/assets/*`, no-cache for HTML) into `out/` when they do not
|
|
187
|
+
exist, so Cloudflare Pages / Netlify deploys "just work". [v1 F3.7]
|
|
188
|
+
- `docs/en/13-deployment.md` — VPS + nginx, Cloudflare Pages, S3/CloudFront,
|
|
189
|
+
Netlify and GitHub Pages recipes; cache-control matrix; GitHub Actions
|
|
190
|
+
release sketch; troubleshooting (deep-link 404, HTML caching, `[object Object]`).
|
|
191
|
+
[v1 F3.8 / F3.9]
|
|
192
|
+
- `test/release-pipeline.test.mjs` — end-to-end test: scaffold a temp app,
|
|
193
|
+
symlink the local framework, run `mado release`, assert that `out/index.html`,
|
|
194
|
+
`out/baked/index.html`, `out/baked/sitemap.xml`, `out/_redirects`, `out/_headers`,
|
|
195
|
+
and copied `public/` assets are all present. [v1 F3.10]
|
|
196
|
+
|
|
197
|
+
### Changed
|
|
198
|
+
- `scripts/preview.mjs` now reads `mado.config.json` (`build.out`, `dev.port`),
|
|
199
|
+
refuses to auto-build by default in app-mode, and asks the user to run
|
|
200
|
+
`mado release` first. Legacy auto-build is opt-in via `PREVIEW_AUTOBUILD=1`
|
|
201
|
+
for the framework repo. [v1 F3.3]
|
|
202
|
+
- `scripts/bundle.mjs` is now app-mode aware: reads `mado.config.json` for
|
|
203
|
+
defaults, accepts `--entry/--html/--out` flags, and writes hashed bundles
|
|
204
|
+
into `out/assets/` so the new nginx / Cloudflare cache rules apply. The old
|
|
205
|
+
`examples/showcase` defaults are kept only in repo-mode for dogfooding.
|
|
206
|
+
[v1 F3.10]
|
|
207
|
+
- `server/serve.mjs` honors `dev.proxy` from `mado.config.json` and forwards
|
|
208
|
+
matching prefixes (e.g. `/api → http://localhost:3000`) without external
|
|
209
|
+
dependencies. The startup banner prints the active proxy table. [v1 F3.6]
|
|
210
|
+
|
|
211
|
+
### Deferred to v0.7
|
|
212
|
+
- `mado dev` does not yet serve baked routes inline. Workaround: run
|
|
213
|
+
`mado release && mado preview`. [v1 F3.2]
|
|
214
|
+
- `mado check` (bake-safety scan over `bake:` routes) is not exposed yet.
|
|
215
|
+
The loud-error contract in `scripts/bake.mjs` covers the regression case.
|
|
216
|
+
[v1 F3.5]
|
|
217
|
+
|
|
218
|
+
Phase 4 — Core hardening:
|
|
219
|
+
|
|
220
|
+
### Added
|
|
221
|
+
- `computed(fn, { equals })` option to suppress subscriber reruns when an
|
|
222
|
+
observed computed recomputes to an equal value. [v1 F4.3]
|
|
223
|
+
- HTML directives: `unsafeHTML()`, `ref()`, `classMap()` and `styleMap()` are
|
|
224
|
+
exported from the public API. Runtime bindings enforce valid positions and
|
|
225
|
+
clean up stale classes/styles/refs on updates and disposal. Bake can serialize
|
|
226
|
+
the static directive shapes it can safely represent. [v1 F4.4]
|
|
227
|
+
- `useForm()` now supports async validators via form-level `validateAsync`,
|
|
228
|
+
field-level `validateAsync`, `validating` / `validatingFields`, and explicit
|
|
229
|
+
`validate()` / `validateField()` methods. [v1 F4.5]
|
|
230
|
+
- `useForm().array(name)` adds a small field-array helper with dotted path names
|
|
231
|
+
(`items.0.title`) and wildcard schema validation (`items.*.title`). [v1 F4.5]
|
|
232
|
+
- `test/signal-cycle.test.mjs` covers self-triggering effect cycle detection.
|
|
233
|
+
[v1 F4.2]
|
|
234
|
+
- `test/html-directives.test.mjs` covers directive rendering, cleanup and
|
|
235
|
+
invalid child-position usage. [v1 F4.4]
|
|
236
|
+
- `test/forms.test.mjs` covers async validator races, async submit blocking,
|
|
237
|
+
and field-array wildcard validation. [v1 F4.5]
|
|
238
|
+
- Phase 4 now has an explicit coverage audit tying every core-hardening task to
|
|
239
|
+
its regression tests. [v1 F4.9]
|
|
240
|
+
|
|
241
|
+
### Changed
|
|
242
|
+
- `computed()` now releases dependency subscriptions after unobserved reads and
|
|
243
|
+
after the last subscriber is disposed, avoiding long-lived stale subscriptions
|
|
244
|
+
in the signal graph. [v1 F4.1]
|
|
245
|
+
- The effect scheduler now detects runaway self-triggering cycles and emits a
|
|
246
|
+
clear diagnostic instead of flushing forever. [v1 F4.2]
|
|
247
|
+
- Runtime head management now clears Mado-managed tags on every navigation,
|
|
248
|
+
including pages without `head()` and pages whose `head()` throws, so stale
|
|
249
|
+
baked/runtime SEO tags cannot leak across routes. [v1 F4.8]
|
|
250
|
+
- Router navigation now saves/restores scroll positions for back/forward,
|
|
251
|
+
scrolls new navigations to the top, and moves focus to the main content
|
|
252
|
+
landmark after navigation. [v1 F4.6]
|
|
253
|
+
- `routes()` now supports a global `errorPage(err, params)` route boundary for
|
|
254
|
+
lazy loader, `load()` and `view()` errors, while local `page.errorView` still
|
|
255
|
+
wins. [v1 F4.7]
|
|
256
|
+
|
|
257
|
+
Phase 5 — Documentation:
|
|
258
|
+
|
|
259
|
+
### Added
|
|
260
|
+
- `docs/en/10-app-architecture.md`, `14-testing.md`, `15-error-handling.md`
|
|
261
|
+
and `16-bake-cookbook.md` complete the v1 English recipe set. [v1 F5.1-F5.4]
|
|
262
|
+
- `AGENTS.md` now includes an "App architecture for LLM" section and `llms.txt`
|
|
263
|
+
links the v1 architecture, layout, auth/API, deployment, testing,
|
|
264
|
+
error-handling and bake docs. [v1 F5.5-F5.6]
|
|
265
|
+
- Russian, French and Ukrainian documentation now includes localized versions of
|
|
266
|
+
the v1 recipe docs `10` through `16`. [v1 F5.7]
|
|
267
|
+
|
|
3
268
|
## 0.5.1
|
|
4
269
|
|
|
5
270
|
Patch release focused on first-user DX after the public npm launch.
|
package/MADO_V1_PLAN.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# MadoJS — Road to v1 (completed v0.6 tracker)
|
|
2
|
+
|
|
3
|
+
> Completed tracker for the v0.6 product-surface push. The work agreed during
|
|
4
|
+
> the v1 audit is now closed and squash-merged into `main` as
|
|
5
|
+
> `feat: add v1 product surface`.
|
|
6
|
+
>
|
|
7
|
+
> Convention: every commit/PR that advances v1 references task IDs in its message,
|
|
8
|
+
> e.g. `[v1 F1.2] bake.mjs: app-mode defaults + --entry/--template/--out flags`.
|
|
9
|
+
> When a task is completed, tick its box here in the same commit.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 0. Mental model (write this into docs first)
|
|
14
|
+
|
|
15
|
+
Three artifact states. One deploy artifact. End of story.
|
|
16
|
+
|
|
17
|
+
| Folder | What it is | Who writes | Who reads | Deployed? |
|
|
18
|
+
|-------------|----------------------------------------------------------------|-------------------|----------------------------|-------------------|
|
|
19
|
+
| `src/` | your source (TS) | you | `tsc`, `esbuild` | no |
|
|
20
|
+
| `dist/` | `tsc` output (native ESM JS for the browser) | `mado build` | `mado dev`, dev browser | no (internal) |
|
|
21
|
+
| `public/` | static assets (favicons, images, robots.txt) | you | `mado bundle` copies it | as part of `out/` |
|
|
22
|
+
| `out/` | **the only deploy artifact**: SPA shell + bundles + baked HTML | `mado release` | nginx / CDN / CF / VPS | ✅ yes |
|
|
23
|
+
|
|
24
|
+
One-liner for users:
|
|
25
|
+
> Develop with `mado dev`. To deploy: run `mado release`, then upload `out/` anywhere.
|
|
26
|
+
|
|
27
|
+
`mado release` = `typecheck` + `build` + `bundle` + `bake` + copy `public/*` → `out/`.
|
|
28
|
+
One command. One artifact. Zero questions about where things live.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 1. Problem map (consolidated)
|
|
33
|
+
|
|
34
|
+
### Layer A — Core (from the audit)
|
|
35
|
+
- **A1** Computed leaks: no refcount/owner; once read, computed stays subscribed to deps forever.
|
|
36
|
+
- **A2** No cycle-detection in `effect` (e.g. `effect(() => x.set(x()+1))` runs forever).
|
|
37
|
+
- **A3** No `equals` option on `computed`.
|
|
38
|
+
- **A4** No template directives: `unsafeHTML`, `ref`, `classMap`, `styleMap`.
|
|
39
|
+
- **A5** `useForm`: no async validators, no field-arrays.
|
|
40
|
+
- **A6** `resource`/`invalidate`: no typed key relationship; pattern miss is silent.
|
|
41
|
+
- **A7** Router: no scroll restoration / focus management / error boundary.
|
|
42
|
+
- **A8** `head()`: not obvious how dedup/cleanup happens across navigation.
|
|
43
|
+
|
|
44
|
+
### Layer B — DX, tooling, product surface (from dogfooding)
|
|
45
|
+
- **B1** CLI/bake hardcoded to `examples/` and alias `@madojs/mado → src/index.ts` — repo-mode leaks into user apps.
|
|
46
|
+
- **B2** No single blessed way for **layouts** (LLM and humans both guess).
|
|
47
|
+
- **B3** No blessed way for **auth + API client + dev-proxy**.
|
|
48
|
+
- **B4** No single config file (`mado.config.json`); everything is env vars.
|
|
49
|
+
- **B5** Unclear model for `dist/` vs `out/` vs `public/`.
|
|
50
|
+
- **B6** No `mado release` (one deploy artifact).
|
|
51
|
+
- **B7** Bake silently renders `[object Object]` for `each()`.
|
|
52
|
+
- **B8** Bake lives "next to" the app instead of inside `mado dev`.
|
|
53
|
+
- **B9** No route guard API.
|
|
54
|
+
- **B10** `crud` starter looks like raw scaffold; no admin-template.
|
|
55
|
+
- **B11** Docs missing: app-architecture, layouts, auth-and-api, deployment, testing, error-handling, bake-cookbook.
|
|
56
|
+
- **B12** Starter scaffolds contain `examples/` legacy.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 2. Phases (deliver in order; phase 5 runs in parallel)
|
|
61
|
+
|
|
62
|
+
### 🟦 Phase 1 — Repo-vs-app split (P0)
|
|
63
|
+
|
|
64
|
+
Goal: kill `examples/` leakage; make app-mode the default.
|
|
65
|
+
|
|
66
|
+
### 🟩 Phase 2 — One blessed way (P0)
|
|
67
|
+
|
|
68
|
+
Goal: conventions over flexibility. Layouts, guards, auth, api — one recipe each.
|
|
69
|
+
|
|
70
|
+
### 🟨 Phase 3 — Bake first-class + Release pipeline (P0)
|
|
71
|
+
|
|
72
|
+
Goal: pragmatic path from `mado dev` to production on VPS / Cloudflare / static CDN.
|
|
73
|
+
|
|
74
|
+
### 🟪 Phase 4 — Core hardening (P1)
|
|
75
|
+
|
|
76
|
+
Goal: long-term correctness of signals, html, router, forms, head.
|
|
77
|
+
|
|
78
|
+
### 🟫 Phase 5 — Documentation (P0/P1, in parallel)
|
|
79
|
+
|
|
80
|
+
Goal: a backender can ship an admin app reading only the docs.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 3. Acceptance scenario for v1
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm exec --package @madojs/mado@latest -- mado init dashboard --starter admin
|
|
88
|
+
cd dashboard
|
|
89
|
+
npm install
|
|
90
|
+
mado dev
|
|
91
|
+
# / → public landing
|
|
92
|
+
# /admin → redirected to /login (guard works)
|
|
93
|
+
# log in → admin shell with sidebar / topbar / dashboard / orders table
|
|
94
|
+
|
|
95
|
+
mado release
|
|
96
|
+
rsync -avz out/ user@vps:/var/www/dashboard/
|
|
97
|
+
# done
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If a backend developer reaches production **without reading `bake.mjs`,
|
|
101
|
+
without setting env vars, without asking "where does layout live?",
|
|
102
|
+
and without an `examples/` folder in their app** — v1 is done.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 4. Tracker
|
|
107
|
+
|
|
108
|
+
### Phase 1 — Repo-vs-app split ✅
|
|
109
|
+
- [x] **F1.1** `mado.config.json` schema + loader (`scripts/_config.mjs`)
|
|
110
|
+
- [x] **F1.2** `scripts/bake.mjs`: flags `--entry/--template/--out/--base-url`, app-mode defaults, no `examples/` alias in app-mode, loud errors instead of silent `[object Object]`
|
|
111
|
+
- [x] **F1.3** `scripts/cli.mjs`: detect repo vs app, read `mado.config.json`, redesigned help, new `mado release` command
|
|
112
|
+
- [x] **F1.4** Starters cleanup: `mado.config.json` and blessed CLI scripts in `starters/minimal` and `starters/crud`; no `examples/` references
|
|
113
|
+
- [x] **F1.5** `docs/en/02-project-layout.md` rewritten around the canonical `src/`/`dist/`/`public/`/`out/` model and `mado.config.json`
|
|
114
|
+
- [x] **F1.6** `test/config-loader.test.mjs` + `test/bake-cli.test.mjs`.
|
|
115
|
+
|
|
116
|
+
### Phase 2 — One blessed way ✅
|
|
117
|
+
- [x] **F2.1** `layout()` factory (alias of `nested()`) exported from `src/page.ts`; flatten propagates layouts outer → inner.
|
|
118
|
+
- [x] **F2.2** `Guard` type + guard chain in `src/router/manifest.ts`. Verdicts: void / `{ halt: true }` / `{ redirect, replace? }`. Async-aware with sync fast path; throwing guard is treated as `halt` with a `console.error`.
|
|
119
|
+
- [x] **F2.3** `layout`, `Guard`, `GuardResult`, `nested`, `navigate` exported from `src/index.ts`.
|
|
120
|
+
- [x] **F2.4** New starter `starters/admin/` with `layouts/{app,auth}.ts`, `lib/{api,auth}.ts`, `components/{x-button,x-input}.ts`, `pages/{home,login,not-found,admin/{dashboard,orders,order-detail}}.ts`, `styles/global.ts`, `mado.config.json`, `public/favicon.svg`. End-to-end scaffold + typecheck + build verified locally.
|
|
121
|
+
- [x] **F2.5** CLI advertises `--starter admin` (`mado init my-app --starter admin`) and adds it to the help screen.
|
|
122
|
+
- [x] **F2.6** Doc `docs/en/11-layouts.md` (one path + 2 alternatives with caveats).
|
|
123
|
+
- [x] **F2.7** Doc `docs/en/12-auth-and-api.md` (blessed `api`/`auth` recipes, backend contract, dev-proxy hint).
|
|
124
|
+
- [x] **F2.8** `test/guards-layouts.test.mjs` covers the public `layout()` alias, sync pass/halt/redirect verdicts, async guards, parent→page guard order, and throwing-guard fallback (7 tests, all green).
|
|
125
|
+
|
|
126
|
+
### Phase 3 — Bake first-class + Release pipeline ✅ (core)
|
|
127
|
+
- [x] **F3.1** `mado release` command: typecheck + build + bundle + bake + copy `public/` → `out/` + write `_headers` / `_redirects` (`scripts/cli.mjs`).
|
|
128
|
+
- [x] **F3.2** Deferred to v0.7: `mado dev` serves baked routes inline. Current v1 path is `mado release && mado preview`.
|
|
129
|
+
- [x] **F3.3** `mado preview` reads `mado.config.json`, refuses to auto-build in app-mode (opt in with `PREVIEW_AUTOBUILD=1`), and emulates nginx fallback (`scripts/preview.mjs`).
|
|
130
|
+
- [x] **F3.4** Bake raises a loud, file/route-targeted error on unsupported render values (e.g. `each()` directive objects). Covered by `test/bake-cli.test.mjs`.
|
|
131
|
+
- [x] **F3.5** Deferred to v0.7: `mado check` runs bake-safety scan on `bake:` routes. Current v1 coverage is the loud-error contract from F3.4.
|
|
132
|
+
- [x] **F3.6** Dev-proxy in `server/serve.mjs`: reads `dev.proxy` from `mado.config.json` and forwards matching prefixes to the upstream backend without external deps.
|
|
133
|
+
- [x] **F3.7** `mado release` generates `out/_redirects` (`/* /index.html 200`) and `out/_headers` (immutable for `/assets/*`, no-cache for `/*.html`) when those files do not exist.
|
|
134
|
+
- [x] **F3.8** Doc `docs/en/13-deployment.md` (VPS + nginx, Cloudflare Pages, S3/CloudFront, Netlify, GitHub Pages, CI sketch, cache matrix, troubleshooting).
|
|
135
|
+
- [x] **F3.9** Production `nginx.conf` next to the docs (already shipped, with `gzip_static`, immutable hashed bundles, SPA fallback). Verified referenced from the deployment doc.
|
|
136
|
+
- [x] **F3.10** `test/release-pipeline.test.mjs`: end-to-end CLI test scaffolds an app, runs `mado release`, and asserts `out/index.html`, `out/baked/index.html`, `out/_headers`, `out/_redirects`, public-asset copy, and sitemap. Also `scripts/bundle.mjs` is app-mode aware (no `examples/`-leak when run from a user app).
|
|
137
|
+
|
|
138
|
+
### Phase 4 — Core hardening
|
|
139
|
+
- [x] **F4.1** Refcount/GC for `computed` in `src/signal.ts` + tests (`computed` releases dep subscriptions after unobserved reads and after the last subscriber is disposed).
|
|
140
|
+
- [x] **F4.2** Cycle-detection in `effect` + `test/signal-cycle.test.mjs`
|
|
141
|
+
- [x] **F4.3** `equals` option on `computed`
|
|
142
|
+
- [x] **F4.4** Directives: `unsafeHTML`, `ref`, `classMap`, `styleMap` in `src/html/bindings.ts` + public exports + `test/html-directives.test.mjs`.
|
|
143
|
+
- [x] **F4.5** `useForm`: async validators (`validateAsync`, field-level `validateAsync`, `validating`) + field arrays (`form.array()`, dotted paths, wildcard schema) + tests.
|
|
144
|
+
- [x] **F4.6** Router: scroll restoration + focus management
|
|
145
|
+
- [x] **F4.7** Router: `errorPage:` in manifest + error boundary
|
|
146
|
+
- [x] **F4.8** `src/head.ts`: guaranteed cleanup on navigation (`data-mado-head` removed before re-applying)
|
|
147
|
+
- [x] **F4.9** Tests for everything above: `test/computed-lazy.test.mjs` (F4.1/F4.3), `test/signal-cycle.test.mjs` (F4.2), `test/html-directives.test.mjs` (F4.4), `test/forms.test.mjs` (F4.5), `test/router-isolation.test.mjs` (F4.6), `test/router-error-boundary.test.mjs` (F4.7), `test/head.test.mjs` (F4.8). Final `typecheck + build + test` pass verified.
|
|
148
|
+
|
|
149
|
+
### Phase 5 — Documentation (parallel to phases 2-4)
|
|
150
|
+
English docs for project layout, layouts, auth/API and deployment exist now.
|
|
151
|
+
The remaining work is deeper recipes plus translation sync.
|
|
152
|
+
|
|
153
|
+
- [x] **F5.1** `docs/en/10-app-architecture.md` (end-to-end admin)
|
|
154
|
+
- [x] **F5.2** `docs/en/14-testing.md`
|
|
155
|
+
- [x] **F5.3** `docs/en/15-error-handling.md`
|
|
156
|
+
- [x] **F5.4** `docs/en/16-bake-cookbook.md`
|
|
157
|
+
- [x] **F5.5** `AGENTS.md`: section "App architecture for LLM"
|
|
158
|
+
- [x] **F5.6** `llms.txt`: new anchors
|
|
159
|
+
- [x] **F5.7** ru/fr/uk translations for new docs (`10` through `16`)
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 5. Working loop
|
|
164
|
+
|
|
165
|
+
1. Pick the first unchecked box.
|
|
166
|
+
2. Implement it (small, focused change).
|
|
167
|
+
3. Run `npm test` (and `npm run typecheck` when touching `src/`).
|
|
168
|
+
4. Tick the box in this file in the same commit.
|
|
169
|
+
5. Add a one-line entry under "Unreleased" in `CHANGELOG.md`.
|
|
170
|
+
6. After each phase finishes, pause and review.
|
|
171
|
+
|
|
172
|
+
## 6. Context-loss safety
|
|
173
|
+
|
|
174
|
+
- This file = ground truth on disk.
|
|
175
|
+
- `task_progress` in chat = current phase/task.
|
|
176
|
+
- Git commits tagged `[v1 Fx.y]` = time machine.
|
|
177
|
+
|
|
178
|
+
If future work resumes from this plan, treat it as archive context. New tasks
|
|
179
|
+
belong in `ROADMAP.md`, `TODO.md`, or a fresh tracker.
|
package/README.md
CHANGED
|
@@ -91,12 +91,20 @@ enough for serious admin apps while remaining small and readable.
|
|
|
91
91
|
npm exec --package @madojs/mado@latest -- mado init my-app
|
|
92
92
|
cd my-app
|
|
93
93
|
npm install
|
|
94
|
-
npm run
|
|
95
|
-
npm run serve
|
|
94
|
+
npm run dev
|
|
96
95
|
```
|
|
97
96
|
|
|
98
|
-
Use the
|
|
99
|
-
|
|
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.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm exec --package @madojs/mado@latest -- mado init dashboard --starter admin
|
|
102
|
+
cd dashboard
|
|
103
|
+
npm install
|
|
104
|
+
npm run dev
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Use the CRUD starter when you want a compact resource/mutation/forms example:
|
|
100
108
|
|
|
101
109
|
```bash
|
|
102
110
|
npm exec --package @madojs/mado@latest -- mado init my-app --starter crud
|
|
@@ -151,17 +159,19 @@ The developer convenience CLI is available as `mado`:
|
|
|
151
159
|
|
|
152
160
|
```bash
|
|
153
161
|
mado init my-app
|
|
162
|
+
mado init dashboard --starter admin
|
|
154
163
|
mado init my-app --starter crud
|
|
164
|
+
mado dev
|
|
155
165
|
mado build
|
|
156
166
|
mado typecheck
|
|
157
167
|
mado test
|
|
168
|
+
mado release
|
|
169
|
+
mado preview
|
|
158
170
|
mado serve basic
|
|
159
171
|
mado dev showcase
|
|
160
172
|
mado examples
|
|
161
173
|
```
|
|
162
174
|
|
|
163
|
-
The CLI is useful before v1, but its command polish may still change.
|
|
164
|
-
|
|
165
175
|
## Documentation
|
|
166
176
|
|
|
167
177
|
- [Language index](./docs/README.md)
|
|
@@ -181,6 +191,13 @@ Core topics:
|
|
|
181
191
|
- [For backenders](./docs/en/06-for-backenders.md)
|
|
182
192
|
- [LLM pitfalls](./docs/en/07-llm-pitfalls.md)
|
|
183
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)
|
|
184
201
|
|
|
185
202
|
AI-agent entrypoints:
|
|
186
203
|
|
|
@@ -327,7 +344,8 @@ html`
|
|
|
327
344
|
|
|
328
345
|
Validation is schema-based and intentionally close to native HTML constraints:
|
|
329
346
|
`required`, `min`, `max`, `pattern`, `type=email/url/number`, plus optional
|
|
330
|
-
custom `validate(values)`.
|
|
347
|
+
custom `validate(values)`. Async validators and field arrays are available via
|
|
348
|
+
`validateAsync`, `validateField()` and `form.array("items")`.
|
|
331
349
|
|
|
332
350
|
Only the root import is the stable public API:
|
|
333
351
|
|
|
@@ -347,16 +365,16 @@ Cloudflare Worker edge-prerender PoC in [`examples/cloudflare`](./examples/cloud
|
|
|
347
365
|
|
|
348
366
|
## Production Bundle
|
|
349
367
|
|
|
350
|
-
Native ESM is the default development
|
|
351
|
-
|
|
368
|
+
Native ESM is the default development path. For production, use the one-command
|
|
369
|
+
release pipeline:
|
|
352
370
|
|
|
353
371
|
```bash
|
|
354
|
-
|
|
355
|
-
|
|
372
|
+
mado release
|
|
373
|
+
mado preview
|
|
356
374
|
```
|
|
357
375
|
|
|
358
|
-
`
|
|
359
|
-
|
|
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.
|
|
360
378
|
|
|
361
379
|
## Tests
|
|
362
380
|
|
package/ROADMAP.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Roadmap
|
|
2
2
|
|
|
3
|
-
Mado is pre-
|
|
4
|
-
|
|
3
|
+
Mado is still pre-1.0, but the v0.6 product-surface push is complete. The goal
|
|
4
|
+
from here is not to grow sideways, but to keep the runtime small, readable and
|
|
5
|
+
reliable under real application pressure.
|
|
5
6
|
|
|
6
7
|
## Current Focus
|
|
7
8
|
|
|
@@ -12,12 +13,31 @@ readable and reliable under real application pressure.
|
|
|
12
13
|
- Keep English as the public/default project language, with localized docs in
|
|
13
14
|
`docs/ru`, `docs/fr` and `docs/uk`.
|
|
14
15
|
|
|
15
|
-
##
|
|
16
|
+
## Completed in v0.6
|
|
17
|
+
|
|
18
|
+
- **Phase 1 — Repo-vs-app split.** Kill `examples/`-leakage from CLI and bake;
|
|
19
|
+
introduce `mado.config.json`; app-mode becomes the default for `mado bake`,
|
|
20
|
+
`mado bundle`, `mado preview`.
|
|
21
|
+
- **Phase 2 — One blessed way.** First-class `layout()` + nested manifest;
|
|
22
|
+
`Guard` API with `redirect`/`halt`; blessed `--starter admin` starter with
|
|
23
|
+
blessed `api`/`auth` recipes; docs for layouts and auth-and-api.
|
|
24
|
+
- **Phase 3 — Bake first-class + Release pipeline.** `mado release` as the
|
|
25
|
+
single deploy command (`dist` internal, `out` deployed); `mado dev` serves
|
|
26
|
+
baked routes inline; bake stops silently rendering `[object Object]`;
|
|
27
|
+
deployment doc with VPS / Cloudflare Pages / static-CDN recipes.
|
|
28
|
+
- **Phase 4 — Core hardening.** Computed GC + cycle-detection in `effect`;
|
|
29
|
+
template directives (`unsafeHTML`, `ref`, `classMap`, `styleMap`); async
|
|
30
|
+
validators and field-arrays in `useForm`; scroll restoration, focus
|
|
31
|
+
management and error boundary in the router; head cleanup on navigation.
|
|
32
|
+
- **Phase 5 — Documentation (parallel).** `10-app-architecture.md`,
|
|
33
|
+
`11-layouts.md`, `12-auth-and-api.md`, `13-deployment.md`, `14-testing.md`,
|
|
34
|
+
`15-error-handling.md`, `16-bake-cookbook.md`; AGENTS.md app-architecture
|
|
35
|
+
section; ru/fr/uk translations.
|
|
36
|
+
|
|
37
|
+
The detailed completed tracker lives in [`MADO_V1_PLAN.md`](./MADO_V1_PLAN.md).
|
|
38
|
+
|
|
39
|
+
## Remaining Before 1.0
|
|
16
40
|
|
|
17
|
-
- Generated app DX: `mado dev`/`serve`/starter scripts should feel as polished
|
|
18
|
-
outside the framework repo as they do inside it.
|
|
19
|
-
- Generated app production story: `mado bundle` and `mado preview` should work
|
|
20
|
-
from a starter app without repository-only assumptions.
|
|
21
41
|
- Browser compatibility pass across current Chrome, Edge, Firefox and Safari.
|
|
22
42
|
- Accessibility pass for examples and common component patterns.
|
|
23
43
|
- Public API audit: names, warnings, lifecycle rules, docs coverage.
|
|
@@ -55,6 +75,7 @@ readable and reliable under real application pressure.
|
|
|
55
75
|
| 2026-06-06 | Mado rebrand | Public package/import name `@madojs/mado`, CLI `mado`, brand/docs/examples updated, internal legacy markers cleaned. |
|
|
56
76
|
| 2026-06-06 | Public polish | English public surface, localized docs, translated code comments/examples/templates/GitHub files. |
|
|
57
77
|
| 2026-06-07 | First npm release | Published `@madojs/mado@0.5.0` with the `mado` CLI, minimal/crud starters, CI and release workflow. |
|
|
78
|
+
| 2026-06-09 | v0.6 product surface | App-mode CLI/config split, admin starter, release pipeline, core hardening, v1 recipe docs and localized docs. |
|
|
58
79
|
|
|
59
80
|
## Future Ideas
|
|
60
81
|
|