@madojs/mado 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/AGENTS.md +291 -0
  2. package/CHANGELOG.md +23 -0
  3. package/LICENSE +21 -0
  4. package/README.md +371 -0
  5. package/ROADMAP.md +52 -0
  6. package/dist/src/component.d.ts +48 -0
  7. package/dist/src/component.js +140 -0
  8. package/dist/src/component.js.map +1 -0
  9. package/dist/src/context.d.ts +40 -0
  10. package/dist/src/context.js +67 -0
  11. package/dist/src/context.js.map +1 -0
  12. package/dist/src/css.d.ts +54 -0
  13. package/dist/src/css.js +137 -0
  14. package/dist/src/css.js.map +1 -0
  15. package/dist/src/devtools.d.ts +22 -0
  16. package/dist/src/devtools.js +63 -0
  17. package/dist/src/devtools.js.map +1 -0
  18. package/dist/src/diagnostics.d.ts +11 -0
  19. package/dist/src/diagnostics.js +28 -0
  20. package/dist/src/diagnostics.js.map +1 -0
  21. package/dist/src/each.d.ts +39 -0
  22. package/dist/src/each.js +35 -0
  23. package/dist/src/each.js.map +1 -0
  24. package/dist/src/forms.d.ts +71 -0
  25. package/dist/src/forms.js +161 -0
  26. package/dist/src/forms.js.map +1 -0
  27. package/dist/src/head.d.ts +19 -0
  28. package/dist/src/head.js +97 -0
  29. package/dist/src/head.js.map +1 -0
  30. package/dist/src/html/bindings.d.ts +78 -0
  31. package/dist/src/html/bindings.js +304 -0
  32. package/dist/src/html/bindings.js.map +1 -0
  33. package/dist/src/html/parser.d.ts +64 -0
  34. package/dist/src/html/parser.js +521 -0
  35. package/dist/src/html/parser.js.map +1 -0
  36. package/dist/src/html/template-types.d.ts +27 -0
  37. package/dist/src/html/template-types.js +8 -0
  38. package/dist/src/html/template-types.js.map +1 -0
  39. package/dist/src/html/template.d.ts +45 -0
  40. package/dist/src/html/template.js +119 -0
  41. package/dist/src/html/template.js.map +1 -0
  42. package/dist/src/html.d.ts +16 -0
  43. package/dist/src/html.js +16 -0
  44. package/dist/src/html.js.map +1 -0
  45. package/dist/src/index.d.ts +35 -0
  46. package/dist/src/index.js +39 -0
  47. package/dist/src/index.js.map +1 -0
  48. package/dist/src/lazy.d.ts +38 -0
  49. package/dist/src/lazy.js +73 -0
  50. package/dist/src/lazy.js.map +1 -0
  51. package/dist/src/lifecycle.d.ts +45 -0
  52. package/dist/src/lifecycle.js +66 -0
  53. package/dist/src/lifecycle.js.map +1 -0
  54. package/dist/src/page.d.ts +161 -0
  55. package/dist/src/page.js +38 -0
  56. package/dist/src/page.js.map +1 -0
  57. package/dist/src/persisted.d.ts +47 -0
  58. package/dist/src/persisted.js +119 -0
  59. package/dist/src/persisted.js.map +1 -0
  60. package/dist/src/resource.d.ts +120 -0
  61. package/dist/src/resource.js +275 -0
  62. package/dist/src/resource.js.map +1 -0
  63. package/dist/src/router/manifest.d.ts +56 -0
  64. package/dist/src/router/manifest.js +302 -0
  65. package/dist/src/router/manifest.js.map +1 -0
  66. package/dist/src/router/match.d.ts +62 -0
  67. package/dist/src/router/match.js +117 -0
  68. package/dist/src/router/match.js.map +1 -0
  69. package/dist/src/router/navigation.d.ts +89 -0
  70. package/dist/src/router/navigation.js +263 -0
  71. package/dist/src/router/navigation.js.map +1 -0
  72. package/dist/src/router.d.ts +13 -0
  73. package/dist/src/router.js +13 -0
  74. package/dist/src/router.js.map +1 -0
  75. package/dist/src/signal.d.ts +67 -0
  76. package/dist/src/signal.js +238 -0
  77. package/dist/src/signal.js.map +1 -0
  78. package/docs/README.md +12 -0
  79. package/docs/en/00-the-mado-way.md +106 -0
  80. package/docs/en/01-routing.md +204 -0
  81. package/docs/en/02-project-layout.md +58 -0
  82. package/docs/en/03-static-bake.md +251 -0
  83. package/docs/en/04-ide-setup.md +162 -0
  84. package/docs/en/05-why-mado.md +193 -0
  85. package/docs/en/06-for-backenders.md +422 -0
  86. package/docs/en/07-llm-pitfalls.md +486 -0
  87. package/docs/en/08-llm-zero-history-test.md +56 -0
  88. package/docs/en/09-shadow-vs-light-dom.md +122 -0
  89. package/docs/en/README.md +16 -0
  90. package/docs/fr/00-the-mado-way.md +108 -0
  91. package/docs/fr/01-routing.md +202 -0
  92. package/docs/fr/02-project-layout.md +58 -0
  93. package/docs/fr/03-static-bake.md +290 -0
  94. package/docs/fr/04-ide-setup.md +162 -0
  95. package/docs/fr/05-why-mado.md +193 -0
  96. package/docs/fr/06-for-backenders.md +432 -0
  97. package/docs/fr/07-llm-pitfalls.md +487 -0
  98. package/docs/fr/08-llm-zero-history-test.md +60 -0
  99. package/docs/fr/09-shadow-vs-light-dom.md +121 -0
  100. package/docs/fr/README.md +16 -0
  101. package/docs/ru/00-the-mado-way.md +93 -0
  102. package/docs/ru/01-routing.md +194 -0
  103. package/docs/ru/02-project-layout.md +57 -0
  104. package/docs/ru/03-static-bake.md +251 -0
  105. package/docs/ru/04-ide-setup.md +144 -0
  106. package/docs/ru/05-why-mado.md +193 -0
  107. package/docs/ru/06-for-backenders.md +422 -0
  108. package/docs/ru/07-llm-pitfalls.md +485 -0
  109. package/docs/ru/08-llm-zero-history-test.md +56 -0
  110. package/docs/ru/09-shadow-vs-light-dom.md +122 -0
  111. package/docs/ru/README.md +14 -0
  112. package/docs/uk/00-the-mado-way.md +54 -0
  113. package/docs/uk/01-routing.md +82 -0
  114. package/docs/uk/02-project-layout.md +46 -0
  115. package/docs/uk/03-static-bake.md +49 -0
  116. package/docs/uk/04-ide-setup.md +26 -0
  117. package/docs/uk/05-why-mado.md +34 -0
  118. package/docs/uk/06-for-backenders.md +50 -0
  119. package/docs/uk/07-llm-pitfalls.md +82 -0
  120. package/docs/uk/08-llm-zero-history-test.md +31 -0
  121. package/docs/uk/09-shadow-vs-light-dom.md +40 -0
  122. package/docs/uk/README.md +16 -0
  123. package/llms.txt +155 -0
  124. package/package.json +81 -0
  125. package/scripts/bake.mjs +406 -0
  126. package/scripts/bundle.mjs +146 -0
  127. package/scripts/cli.mjs +382 -0
  128. package/scripts/new.mjs +80 -0
  129. package/scripts/preview.mjs +176 -0
  130. package/scripts/release-notes.mjs +66 -0
  131. package/scripts/showcase-regression.mjs +392 -0
  132. package/server/serve.mjs +292 -0
  133. package/starters/crud/README.md +21 -0
  134. package/starters/crud/index.html +20 -0
  135. package/starters/crud/package.json +17 -0
  136. package/starters/crud/src/components/app-shell.ts +51 -0
  137. package/starters/crud/src/components/ticket-detail.ts +33 -0
  138. package/starters/crud/src/components/ticket-form.ts +69 -0
  139. package/starters/crud/src/components/ticket-list.ts +66 -0
  140. package/starters/crud/src/lib/api.ts +76 -0
  141. package/starters/crud/src/main.ts +12 -0
  142. package/starters/crud/src/pages/home.ts +18 -0
  143. package/starters/crud/src/pages/not-found.ts +12 -0
  144. package/starters/crud/src/pages/ticket-detail.ts +6 -0
  145. package/starters/crud/src/pages/ticket-new.ts +6 -0
  146. package/starters/crud/src/pages/tickets.ts +6 -0
  147. package/starters/crud/src/routes.ts +9 -0
  148. package/starters/crud/src/styles/global.ts +155 -0
  149. package/starters/crud/tsconfig.json +15 -0
  150. package/starters/minimal/README.md +19 -0
  151. package/starters/minimal/index.html +20 -0
  152. package/starters/minimal/package.json +17 -0
  153. package/starters/minimal/src/components/app-counter.ts +31 -0
  154. package/starters/minimal/src/main.ts +9 -0
  155. package/starters/minimal/src/pages/home.ts +18 -0
  156. package/starters/minimal/src/pages/not-found.ts +14 -0
  157. package/starters/minimal/src/routes.ts +6 -0
  158. package/starters/minimal/src/styles/global.ts +60 -0
  159. package/starters/minimal/tsconfig.json +15 -0
  160. package/templates/page-detail.ts +63 -0
  161. package/templates/page-form.ts +94 -0
  162. package/templates/page-list.ts +79 -0
@@ -0,0 +1,54 @@
1
+ # Шлях Mado
2
+
3
+ > Один зрозумілий шлях. Жорсткі контракти. Мінімум магії.
4
+
5
+ Mado — це не лише набір API, а набір домовленостей. Якщо їх дотримуватись,
6
+ проєкт залишається читабельним навіть тоді, коли в ньому десятки сторінок і
7
+ кілька розробників.
8
+
9
+ ## Принципи
10
+
11
+ 1. **Один спосіб.** Для типової задачі має бути один канонічний шлях, а не п’ять
12
+ рівноправних стилів.
13
+ 2. **Явність замість магії.** Немає сканерів файлів, прихованих глобалів і
14
+ неочевидних side effects.
15
+ 3. **Платформа спочатку.** Якщо браузер уже має потрібну можливість, Mado дає
16
+ тонку обгортку, а не переписує платформу.
17
+ 4. **Суворий TypeScript.** `tsc --strict` — базовий контракт.
18
+ 5. **Нуль runtime-залежностей.** Кожна залежність — це довгострокове
19
+ зобов’язання.
20
+
21
+ ## Базова структура
22
+
23
+ ```text
24
+ src/
25
+ ├── routes.ts
26
+ ├── main.ts
27
+ ├── pages/
28
+ ├── components/
29
+ ├── layouts/
30
+ ├── lib/
31
+ └── styles/
32
+ ```
33
+
34
+ Кожна сторінка живе в окремому файлі та експортує `page({...})`.
35
+ Компоненти реєструються через `component()`. Дані читаються через `resource()`,
36
+ зміни виконуються через `mutation()`, списки рендеряться через `each()`.
37
+
38
+ ## Імена компонентів
39
+
40
+ Єдине правило браузера: ім’я custom element має містити дефіс. `x-*` у прикладах
41
+ Mado — це демо-конвенція, а не вимога фреймворку. У production краще брати
42
+ префікс домену: `app-*`, `crm-*`, `ticket-*`, `admin-*`.
43
+
44
+ ## Чого не робимо
45
+
46
+ - Не пишемо JSX або Vue-шаблони.
47
+ - Не читаємо сигнал через `.value`; сигнал читається як функція: `count()`.
48
+ - Не використовуємо `disabled=${...}` для булевих атрибутів; треба
49
+ `?disabled=${...}`.
50
+ - Не рендеримо динамічні списки через `.map()` там, де потрібне збереження DOM
51
+ стану; використовуємо `each()`.
52
+ - Не додаємо runtime-залежності без дуже вагомої причини.
53
+
54
+ Коли є сумнів, краще додати рецепт у документацію, ніж новий primitive в core.
@@ -0,0 +1,82 @@
1
+ # Маршрутизація
2
+
3
+ Mado використовує явний route manifest: один файл показує весь URL-граф
4
+ застосунку.
5
+
6
+ ```ts
7
+ import { routes } from "@madojs/mado";
8
+
9
+ export const manifest = {
10
+ "/": () => import("./pages/home.js"),
11
+ "/users/:id": () => import("./pages/user-detail.js"),
12
+ "*": () => import("./pages/not-found.js"),
13
+ };
14
+
15
+ export default routes(manifest);
16
+ ```
17
+
18
+ ## Сторінка
19
+
20
+ ```ts
21
+ import { page, html } from "@madojs/mado";
22
+
23
+ export default page<{ id: string }>({
24
+ title: ({ id }) => `User ${id}`,
25
+ view: ({ params }) => html`<x-user data-id=${params.id}></x-user>`,
26
+ });
27
+ ```
28
+
29
+ Сторінка може мати `title`, `head`, `load`, `view`, `errorView` і `bake`.
30
+ Маршрут може бути lazy import або готовим `page({...})`.
31
+
32
+ ## Nested routes
33
+
34
+ ```ts
35
+ import { nested, routes } from "@madojs/mado";
36
+
37
+ export const manifest = {
38
+ "/": () => import("./pages/home.js"),
39
+ "/app": nested({
40
+ layout: () => import("./layouts/app-layout.js"),
41
+ routes: {
42
+ "/dashboard": () => import("./pages/dashboard.js"),
43
+ "/settings": () => import("./pages/settings.js"),
44
+ },
45
+ }),
46
+ };
47
+
48
+ export default routes(manifest);
49
+ ```
50
+
51
+ Layout отримує дочірній view і може рендерити shell: nav, sidebar, toolbar,
52
+ notifications.
53
+
54
+ ## Навігація
55
+
56
+ Посилання з `data-link` перехоплюються роутером:
57
+
58
+ ```html
59
+ <a href="/users/42" data-link>Open</a>
60
+ ```
61
+
62
+ Програмна навігація:
63
+
64
+ ```ts
65
+ import { navigate } from "@madojs/mado";
66
+
67
+ navigate("/users/42");
68
+ ```
69
+
70
+ Router підтримує hover-prefetch, stale async guard, scroll-to-top для нової
71
+ навігації та `dispose()` для тестів/dev overlay.
72
+
73
+ ## Query params
74
+
75
+ ```ts
76
+ import { queryParam } from "@madojs/mado";
77
+
78
+ const search = queryParam("q", "");
79
+ search.set("mado");
80
+ ```
81
+
82
+ `queryParam()` повертає signal-like API і синхронізує стан із URL.
@@ -0,0 +1,46 @@
1
+ # Структура проєкту
2
+
3
+ Рекомендована структура Mado-застосунку:
4
+
5
+ ```text
6
+ src/
7
+ ├── main.ts
8
+ ├── routes.ts
9
+ ├── pages/
10
+ ├── components/
11
+ ├── layouts/
12
+ ├── lib/
13
+ └── styles/
14
+ ```
15
+
16
+ ## `main.ts`
17
+
18
+ Точка входу: встановлює глобальні стилі, провайдери контексту та монтує кореневий
19
+ компонент у `#app`.
20
+
21
+ ## `routes.ts`
22
+
23
+ Єдиний manifest маршрутів. Немає file-system routing, груп у назвах папок або
24
+ прихованих conventions.
25
+
26
+ ## `pages/`
27
+
28
+ Одна сторінка — один файл — `export default page({...})`.
29
+
30
+ ## `components/`
31
+
32
+ Повторно використовувані Web Components. Імпорт файлу реєструє компонент як side
33
+ effect.
34
+
35
+ ## `layouts/`
36
+
37
+ Shell для nested routes: admin layout, marketing layout, authenticated area.
38
+
39
+ ## `lib/`
40
+
41
+ API-клієнти, contexts, чиста бізнес-логіка без UI.
42
+
43
+ ## `styles/`
44
+
45
+ Глобальні tokens або shared CSS через `css```. Для app-shell часто зручно
46
+ використовувати Light DOM, для leaf-компонентів — Shadow DOM.
@@ -0,0 +1,49 @@
1
+ # Static Bake & SEO
2
+
3
+ Mado навмисно не робить SSR із hydration. Для SEO-сторінок є `bake`: build-time
4
+ prerender у статичний HTML із meta-тегами, JSON-LD і baked data.
5
+
6
+ ## Коли підходить
7
+
8
+ - Блог, документація, landing pages.
9
+ - Невеликі каталоги з кінцевим набором сторінок.
10
+ - Сторінки, де crawlers мають одразу побачити контент.
11
+ - Контент не персоналізований для конкретного користувача.
12
+
13
+ ## Коли не підходить
14
+
15
+ - Авторизовані dashboards.
16
+ - Персоналізований HTML.
17
+ - Real-time дані.
18
+ - Каталоги, які потребують справжнього server rendering на кожен запит.
19
+
20
+ ## Сторінка з bake
21
+
22
+ ```ts
23
+ import { page, html } from "@madojs/mado";
24
+
25
+ export default page<{ slug: string }, Product>({
26
+ title: ({ slug }) => `Product ${slug}`,
27
+ head: ({ slug }, data) => ({
28
+ description: data?.description ?? `Product ${slug}`,
29
+ }),
30
+ bake: {
31
+ paths: () => products.map((p) => ({ slug: p.slug })),
32
+ data: ({ slug }) => findProduct(slug),
33
+ revalidate: 3600,
34
+ },
35
+ view: ({ params }) => html`<x-product data-slug=${params.slug}></x-product>`,
36
+ });
37
+ ```
38
+
39
+ `bake.paths()` повертає всі params, `bake.data()` повертає дані для конкретної
40
+ сторінки, `head()` формує SEO-метадані.
41
+
42
+ ## Edge prerender
43
+
44
+ Для великих наборів сторінок можна робити той самий підхід на edge: Cloudflare
45
+ Worker генерує HTML на cache miss, кладе в KV і віддає з TTL. Приклад лежить в
46
+ `examples/cloudflare`.
47
+
48
+ Це не hydration. Клієнтський Mado-застосунок все одно стартує нормально і
49
+ перерендерює сторінку після завантаження.
@@ -0,0 +1,26 @@
1
+ # Налаштування IDE
2
+
3
+ Mado використовує tagged templates `html`` і `css``. Для TypeScript це звичайні
4
+ рядки, тому підсвітка HTML/CSS залежить від IDE.
5
+
6
+ ## VS Code
7
+
8
+ Рекомендовано встановити `lit-plugin` або інше розширення, яке розуміє
9
+ `html``/`css`` tagged templates.
10
+
11
+ ## WebStorm
12
+
13
+ WebStorm зазвичай розуміє tagged templates без додаткового налаштування.
14
+
15
+ ## Neovim / Helix
16
+
17
+ Можна використовувати LSP/плагіни для lit-html або inline HTML у template
18
+ strings.
19
+
20
+ ## Що IDE не перевірить
21
+
22
+ - Чи правильно ти обгорнув `count()` у `() => count()`.
23
+ - Чи варто використовувати `?disabled` замість `disabled`.
24
+ - Чи є `.js` у browser ESM imports.
25
+
26
+ Для цього потрібні правила з `AGENTS.md`, тести та уважний review.
@@ -0,0 +1,34 @@
1
+ # Чому Mado
2
+
3
+ Mado не намагається “вбити React” або довести, що всі інші помиляються. Це
4
+ інструмент для людей, які хочуть маленький, читабельний frontend runtime поверх
5
+ нативного браузера.
6
+
7
+ ## Lit
8
+
9
+ Lit чудовий для дизайн-систем і компонентів, які мають жити всередині будь-якого
10
+ framework. Mado краще підходить, коли ти пишеш увесь застосунок і хочеш router,
11
+ data, forms, context і static bake в одному маленькому пакеті.
12
+
13
+ ## Solid
14
+
15
+ Solid швидший і зріліший. Якщо тобі комфортно з JSX transform, Vite і mature
16
+ ecosystem — Solid може бути кращим вибором. Mado обирає інше: browser ESM,
17
+ `tsc`, tagged templates і код, який можна прочитати.
18
+
19
+ ## htmx
20
+
21
+ htmx сильний, коли backend володіє HTML fragments. Mado потрібен тоді, коли все
22
+ ж хочеться SPA: локальний UI state, optimistic updates, query params, cached
23
+ resources, persisted state і lazy modules.
24
+
25
+ ## React / Vue / Svelte
26
+
27
+ Вони мають більші ecosystem, більше відповідей у Google/LLM і більше людей на
28
+ ринку. Mado виграє не масштабом ecosystem, а ownership: маленький runtime,
29
+ нуль runtime-залежностей і зрозумілі правила.
30
+
31
+ ## Головна теза
32
+
33
+ Mado — не найшвидший у synthetic benchmarks і не найбагатший ecosystem. Його
34
+ сенс у тому, що frontend знову можна тримати в голові.
@@ -0,0 +1,50 @@
1
+ # Mado для бекендерів
2
+
3
+ Якщо ти пишеш Go, Rust, .NET, Java, Python або Node backend, Mado можна уявляти
4
+ як маленький HTTP-сервер у браузері.
5
+
6
+ | Backend mental model | Mado |
7
+ |---|---|
8
+ | router | `routes()` |
9
+ | handler | `page().view` |
10
+ | middleware/layout | `nested()` + layout |
11
+ | cache get-or-set | `resource()` |
12
+ | POST/PUT/DELETE | `mutation()` |
13
+ | cache invalidation | `invalidates` / `invalidate()` |
14
+ | dependency injection | `createContext/provide/inject` |
15
+
16
+ ## CRUD
17
+
18
+ ```ts
19
+ const users = resource(
20
+ () => "/api/users",
21
+ jsonFetcher<User[]>(),
22
+ );
23
+
24
+ const save = mutation(api.saveUser, {
25
+ invalidates: ["/api/users*"],
26
+ });
27
+ ```
28
+
29
+ ## Форми
30
+
31
+ ```ts
32
+ const form = useForm({
33
+ email: { required: true, type: "email" },
34
+ });
35
+ ```
36
+
37
+ Mado спирається на Constraint Validation API браузера, а не на окрему validation
38
+ екосистему.
39
+
40
+ ## Auth
41
+
42
+ Auth зазвичай живе в `lib/auth.ts` як signal/context. Protected area зручно
43
+ робити через nested layout, який перевіряє session і показує dashboard або
44
+ redirect/login.
45
+
46
+ ## Правило
47
+
48
+ Не тягни backend-архітектуру в frontend дослівно. Тримай UI state локальним,
49
+ data fetching через `resource()`, mutation через `mutation()`, а shared services
50
+ через context.
@@ -0,0 +1,82 @@
1
+ # Типові помилки LLM у Mado-коді
2
+
3
+ Цей файл потрібен, щоб AI-агенти не писали React/Vue-код у Mado-проєкті.
4
+
5
+ ## JSX
6
+
7
+ ```ts
8
+ // Ні
9
+ const view = <button>{count}</button>;
10
+
11
+ // Так
12
+ const view = html`<button>${count}</button>`;
13
+ ```
14
+
15
+ ## `useState` / `useEffect`
16
+
17
+ ```ts
18
+ // Ні
19
+ const [count, setCount] = useState(0);
20
+
21
+ // Так
22
+ const count = signal(0);
23
+ count.set(1);
24
+ ```
25
+
26
+ ## Signal `.value`
27
+
28
+ ```ts
29
+ // Ні
30
+ count.value
31
+
32
+ // Так
33
+ count()
34
+ ```
35
+
36
+ ## Нереактивний child binding
37
+
38
+ ```ts
39
+ // Нереактивно: count() прочитано один раз
40
+ html`<div>${count() * 2}</div>`;
41
+
42
+ // Реактивно
43
+ html`<div>${() => count() * 2}</div>`;
44
+ ```
45
+
46
+ ## Boolean attributes
47
+
48
+ ```ts
49
+ // Ні
50
+ html`<button disabled=${loading}>Save</button>`;
51
+
52
+ // Так
53
+ html`<button ?disabled=${loading}>Save</button>`;
54
+ ```
55
+
56
+ ## Списки
57
+
58
+ ```ts
59
+ // Не для динамічного reorder
60
+ items().map((item) => html`<li>${item.name}</li>`);
61
+
62
+ // Так
63
+ each(items(), (item) => item.id, (item) => html`<li>${item.name}</li>`);
64
+ ```
65
+
66
+ ## Imports
67
+
68
+ У browser ESM локальні imports мають мати `.js`:
69
+
70
+ ```ts
71
+ import "./components/x-card.js";
72
+ ```
73
+
74
+ ## `resource()` lifecycle
75
+
76
+ `resource()` створюй у component setup або всередині явного lifecycle, щоб cleanup
77
+ відбувався автоматично.
78
+
79
+ ## Component names
80
+
81
+ Custom element name має містити дефіс. `x-*` — демо-конвенція; production може
82
+ мати `app-*`, `crm-*`, `ticket-*`, `admin-*`.
@@ -0,0 +1,31 @@
1
+ # LLM Zero-History Test
2
+
3
+ Мета тесту: перевірити, чи може LLM без попередньої історії написати ідіоматичний
4
+ Mado CRUD, не перетворюючи його на React у tagged templates.
5
+
6
+ ## Дозволений контекст
7
+
8
+ - `AGENTS.md`
9
+ - `README.md`
10
+ - `docs/uk/07-llm-pitfalls.md` або відповідна англійська версія
11
+ - `examples/basic/README.md`
12
+ - конкретні файли прикладів тільки за потреби
13
+
14
+ ## Що перевіряти
15
+
16
+ - Немає JSX, `useState`, `useEffect`.
17
+ - Немає signal `.value`.
18
+ - Reactive child bindings з `count()` обгорнуті у `() =>`.
19
+ - Boolean attributes пишуться як `?disabled`, `?checked`.
20
+ - Динамічні списки використовують `each()`.
21
+ - Imports мають `.js`.
22
+ - `resource()` створюється в lifecycle-aware контексті.
23
+
24
+ ## Артефакт
25
+
26
+ `examples/tickets` — маленький ticket-admin SPA з routes, mock API, forms,
27
+ resources, mutations, invalidation, `queryParam`, `computed`, `signal` і
28
+ keyed lists.
29
+
30
+ Критерій успіху: код виглядає як Mado, а не як React/Vue, переодягнений у
31
+ template strings.
@@ -0,0 +1,40 @@
1
+ # Shadow DOM vs Light DOM
2
+
3
+ Mado використовує Shadow DOM за замовчуванням, але це не означає, що його треба
4
+ вмикати всюди.
5
+
6
+ ## Shadow DOM добре підходить для
7
+
8
+ - leaf-компонентів;
9
+ - isolated widgets;
10
+ - badges, cards, modals, buttons;
11
+ - компонентів, які мають не ламатися від зовнішнього CSS.
12
+
13
+ ```ts
14
+ component("x-badge", () => () => html`<span><slot></slot></span>`, {
15
+ styles: css`:host { display: inline-block; }`,
16
+ });
17
+ ```
18
+
19
+ ## Light DOM краще для
20
+
21
+ - app shell;
22
+ - admin layouts;
23
+ - route-level pages;
24
+ - компонентів, які мають користуватися глобальними utility classes;
25
+ - великих CRUD surfaces, де CSS має бути простим і передбачуваним.
26
+
27
+ ```ts
28
+ component("x-app-layout", () => () => html`<main><slot></slot></main>`, {
29
+ shadow: false,
30
+ styles: css`x-app-layout main { display: grid; }`,
31
+ });
32
+ ```
33
+
34
+ ## Практичне правило
35
+
36
+ Якщо компонент — самостійний reusable visual, бери Shadow DOM. Якщо це частина
37
+ app layout або page composition, часто краще Light DOM.
38
+
39
+ Посилання з `data-link` працюють і в Shadow DOM, бо router використовує
40
+ `event.composedPath()`.
@@ -0,0 +1,16 @@
1
+ # Документація Mado — Українська
2
+
3
+ Український комплект документації.
4
+
5
+ | Розділ | Файл |
6
+ |---|---|
7
+ | Шлях Mado | [00-the-mado-way.md](./00-the-mado-way.md) |
8
+ | Маршрутизація | [01-routing.md](./01-routing.md) |
9
+ | Структура проєкту | [02-project-layout.md](./02-project-layout.md) |
10
+ | Static bake & SEO | [03-static-bake.md](./03-static-bake.md) |
11
+ | Налаштування IDE | [04-ide-setup.md](./04-ide-setup.md) |
12
+ | Чому Mado | [05-why-mado.md](./05-why-mado.md) |
13
+ | Для бекендерів | [06-for-backenders.md](./06-for-backenders.md) |
14
+ | Типові помилки LLM | [07-llm-pitfalls.md](./07-llm-pitfalls.md) |
15
+ | LLM zero-history тест | [08-llm-zero-history-test.md](./08-llm-zero-history-test.md) |
16
+ | Shadow DOM vs Light DOM | [09-shadow-vs-light-dom.md](./09-shadow-vs-light-dom.md) |
package/llms.txt ADDED
@@ -0,0 +1,155 @@
1
+ # Mado
2
+
3
+ > Small native-web SPA framework on the platform (Web Components + signals + tagged-template `html`).
4
+ > No build step (only `tsc`), no runtime dependencies, readable in an evening.
5
+
6
+ Mado is a narrowly-focused frontend framework that deliberately avoids React patterns (no JSX, no hooks, no VDOM, no Vite). Target audience: backend developers and senior frontend engineers who are tired of the infrastructure complexity of React/Next.
7
+
8
+ ## Key things an AI assistant needs to know
9
+
10
+ - **This is NOT React, NOT Lit, NOT Solid.** When generating code for Mado, **do not use JSX, `useState`, `useEffect`, classes, decorators, `requestUpdate`**. That will be an error.
11
+ - **All templates are tagged template `html\`...\``** (not JSX). Allowed bindings inside: `${value}`, `attr=${v}`, `@evt=${fn}`, `.prop=${v}`, `?attr=${flag}`.
12
+ - **Reactivity via signals.** `signal()`, `computed()`, `effect()`. A signal is a getter function (`count()`), not an object field (`count.value`).
13
+ - **Components are Web Components.** Registered via `component('x-name', setupFn, options)`. Names must include a hyphen (`x-foo`, `my-button`).
14
+ - **Cleanup via `ctx.onDispose(fn)`** in setup, not via return from effect.
15
+
16
+ ## Critical template rules
17
+
18
+ 1. **A reactive value in a template = getter function.**
19
+ ```ts
20
+ // ❌ NOT REACTIVE: read once at render time
21
+ html`<div>${count() * 2}</div>`
22
+ // ✅ REACTIVE: subscription
23
+ html`<div>${() => count() * 2}</div>`
24
+ ```
25
+ The signal itself can also be inserted directly — Mado will recognise it as a function:
26
+ ```ts
27
+ html`<div>${count}</div>` // ✅ ok, count is a function
28
+ ```
29
+
30
+ 2. **DOM properties vs HTML attributes:**
31
+ - `attr=${v}` → setAttribute (strings/numbers only);
32
+ - `.prop=${v}` → DOM property (objects, arrays, numbers without serialisation);
33
+ - `?attr=${flag}` → boolean attribute (toggle attribute);
34
+ - `@evt=${fn}` → addEventListener.
35
+
36
+ ```ts
37
+ html`<input ?disabled=${isLoading} .value=${user.name} @input=${onInput}>`
38
+ ```
39
+
40
+ 3. **Lists — must use `each(items, keyFn, renderFn)`**, not `.map()` without a key:
41
+ ```ts
42
+ import { each } from "@madojs/mado";
43
+ html`<ul>${() => each(users(), u => u.id, u => html`<li>${u.name}</li>`)}</ul>`
44
+ ```
45
+
46
+ ## Canonical imports
47
+
48
+ ```ts
49
+ // Everything you normally need — from one place:
50
+ import {
51
+ signal, computed, effect, batch,
52
+ html, render,
53
+ each,
54
+ component,
55
+ css, cssVars,
56
+ routes, router, navigate, queryParam, prefetchPath,
57
+ page, nested,
58
+ resource, mutation, invalidate, jsonFetcher,
59
+ useForm,
60
+ createContext, provide, inject,
61
+ persisted,
62
+ lazy,
63
+ } from "@madojs/mado";
64
+ ```
65
+
66
+ ## Canonical "Hello world"
67
+
68
+ ```ts
69
+ // src/main.ts
70
+ import { html, render } from "@madojs/mado";
71
+ import routesApi from "./routes.js";
72
+ render(html`${routesApi.view}`, document.getElementById("app")!);
73
+
74
+ // src/routes.ts
75
+ import { routes } from "@madojs/mado";
76
+ export default routes({
77
+ "/": () => import("./pages/home.js"),
78
+ "*": () => import("./pages/not-found.js"),
79
+ });
80
+
81
+ // src/pages/home.ts
82
+ import { page, component, html, css, signal } from "@madojs/mado";
83
+
84
+ component("x-counter", () => {
85
+ const count = signal(0);
86
+ return () => html`
87
+ <button @click=${() => count.update(n => n + 1)}>${count}</button>
88
+ `;
89
+ }, { styles: css`button { padding: .5rem 1rem; }` });
90
+
91
+ export default page({
92
+ title: "Home",
93
+ view: () => html`<x-counter></x-counter>`,
94
+ });
95
+ ```
96
+
97
+ ## Canonical CRUD pattern (for backend developers)
98
+
99
+ ```ts
100
+ import { page, html, resource, mutation, each, useForm, navigate } from "@madojs/mado";
101
+ import { api } from "../lib/api.js";
102
+
103
+ const users = resource(() => "/api/users", () => api.list(), { staleTime: 30_000 });
104
+ const create = mutation((u) => api.create(u), { invalidates: ["/api/users*"] });
105
+
106
+ export default page({
107
+ view: () => {
108
+ const f = useForm({ name: { required: true } });
109
+ return html`
110
+ <form @submit=${f.onSubmit(async v => { await create.run(v); navigate("/"); })}>
111
+ <input name="name" @input=${f.onInput}>
112
+ <button ?disabled=${() => !f.isValid()}>Create</button>
113
+ </form>
114
+ ${() => each(users.data() ?? [], u => u.id, u => html`<li>${u.name}</li>`)}
115
+ `;
116
+ },
117
+ });
118
+ ```
119
+
120
+ ## Documentation
121
+
122
+ - README: https://github.com/madojs/mado#readme — full description + cookbook
123
+ - docs/en/00-the-mado-way.md — philosophy and applicability boundaries
124
+ - docs/en/01-routing.md — detailed router documentation
125
+ - docs/en/02-project-layout.md — recommended project structure
126
+ - docs/en/03-static-bake.md — SEO without SSR (static build / edge prerender)
127
+ - docs/en/04-ide-setup.md — VS Code / WebStorm configuration
128
+ - docs/en/05-why-mado.md — honest comparison with Lit / Solid / Svelte / htmx / Alpine / React
129
+ - docs/en/06-for-backenders.md — mental model in 10 minutes for Go/Rust/.NET/Java developers
130
+ - docs/en/07-llm-pitfalls.md — common mistakes when generating Mado code
131
+ - examples/basic/ — minimal API tour
132
+ - examples/tickets/ — LLM zero-history CRUD validation
133
+ - examples/showcase/ — flagship CRM pressure app (auth, nested routes, forms, mutations)
134
+ - examples/cloudflare/ — Edge prerender PoC on Cloudflare Workers
135
+
136
+ ## What Mado does NOT do (intentionally)
137
+
138
+ - ❌ JSX → tagged templates instead
139
+ - ❌ Virtual DOM → fine-grained signal updates
140
+ - ❌ SSR with hydration → `bake` (static build) or edge-prerender for SEO
141
+ - ❌ Hooks and rules of hooks → signals
142
+ - ❌ Mandatory Webpack/Vite → only `tsc`
143
+ - ❌ React-Router / TanStack → built-in 500-line `routes()`
144
+ - ❌ React-Query / SWR → built-in `resource()`
145
+ - ❌ Formik / RHF → built-in `useForm()` (HTML5 validation)
146
+ - ❌ Redux / Zustand → `signal()` + `createContext`
147
+ - ❌ Decorators → plain functions
148
+
149
+ ## Version
150
+
151
+ `0.5.0` — early, API may change before 1.0. Semver is not guaranteed on minor versions before 1.0.
152
+
153
+ ## License
154
+
155
+ MIT.