@madojs/mado 0.10.1 → 0.11.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 (217) hide show
  1. package/AGENTS.md +24 -26
  2. package/CHANGELOG.md +68 -0
  3. package/README.md +18 -45
  4. package/TODO.md +52 -48
  5. package/dist/src/component.d.ts +2 -1
  6. package/dist/src/component.js +5 -2
  7. package/dist/src/component.js.map +1 -1
  8. package/dist/src/each.d.ts +1 -1
  9. package/dist/src/each.js +1 -1
  10. package/dist/src/each.js.map +1 -1
  11. package/dist/src/index.d.ts +11 -6
  12. package/dist/src/index.js +5 -3
  13. package/dist/src/index.js.map +1 -1
  14. package/dist/src/lazy.d.ts +1 -1
  15. package/dist/src/lazy.js +1 -1
  16. package/dist/src/lazy.js.map +1 -1
  17. package/dist/src/page.d.ts +17 -21
  18. package/dist/src/page.js +7 -12
  19. package/dist/src/page.js.map +1 -1
  20. package/dist/src/router/manifest.d.ts +1 -1
  21. package/dist/src/router/manifest.js +21 -13
  22. package/dist/src/router/manifest.js.map +1 -1
  23. package/dist/src/router/match.d.ts +2 -2
  24. package/dist/src/router/match.js +3 -3
  25. package/dist/src/router/match.js.map +1 -1
  26. package/dist/src/router/navigation.js +1 -1
  27. package/dist/src/router/navigation.js.map +1 -1
  28. package/dist/src/vite/index.d.ts +10 -0
  29. package/dist/src/vite/index.js +33 -0
  30. package/dist/src/vite/index.js.map +1 -0
  31. package/docs/en/00-the-mado-way.md +25 -12
  32. package/docs/en/01-routing.md +90 -142
  33. package/docs/en/02-project-layout.md +59 -53
  34. package/docs/en/03-static-bake.md +5 -6
  35. package/docs/en/05-why-mado.md +6 -6
  36. package/docs/en/06-for-backenders.md +18 -22
  37. package/docs/en/08-llm-zero-history-test.md +9 -14
  38. package/docs/en/09-shadow-vs-light-dom.md +28 -36
  39. package/docs/en/10-app-architecture.md +158 -96
  40. package/docs/en/11-layouts.md +22 -24
  41. package/docs/en/12-auth-and-api.md +89 -182
  42. package/docs/en/13-deployment.md +18 -22
  43. package/docs/en/14-testing.md +4 -4
  44. package/docs/en/16-bake-cookbook.md +11 -12
  45. package/docs/en/18-api-freeze-map.md +6 -4
  46. package/docs/en/20-v1-stability.md +1 -1
  47. package/docs/fr/00-the-mado-way.md +55 -90
  48. package/docs/fr/01-routing.md +70 -152
  49. package/docs/fr/02-project-layout.md +61 -42
  50. package/docs/fr/03-static-bake.md +1 -1
  51. package/docs/fr/05-why-mado.md +6 -6
  52. package/docs/fr/06-for-backenders.md +7 -7
  53. package/docs/fr/08-llm-zero-history-test.md +21 -48
  54. package/docs/fr/09-shadow-vs-light-dom.md +43 -162
  55. package/docs/fr/10-app-architecture.md +110 -33
  56. package/docs/fr/11-layouts.md +24 -12
  57. package/docs/fr/12-auth-and-api.md +63 -22
  58. package/docs/fr/13-deployment.md +7 -10
  59. package/docs/fr/14-testing.md +1 -1
  60. package/docs/fr/16-bake-cookbook.md +2 -2
  61. package/docs/fr/18-api-freeze-map.md +1 -1
  62. package/docs/fr/20-v1-stability.md +1 -1
  63. package/docs/recipes/nginx/README.md +13 -0
  64. package/docs/ru/00-the-mado-way.md +53 -75
  65. package/docs/ru/01-routing.md +68 -143
  66. package/docs/ru/02-project-layout.md +61 -41
  67. package/docs/ru/03-static-bake.md +2 -2
  68. package/docs/ru/05-why-mado.md +6 -6
  69. package/docs/ru/06-for-backenders.md +7 -7
  70. package/docs/ru/08-llm-zero-history-test.md +9 -14
  71. package/docs/ru/09-shadow-vs-light-dom.md +43 -178
  72. package/docs/ru/10-app-architecture.md +115 -63
  73. package/docs/ru/11-layouts.md +24 -24
  74. package/docs/ru/12-auth-and-api.md +57 -35
  75. package/docs/ru/13-deployment.md +7 -11
  76. package/docs/ru/14-testing.md +1 -1
  77. package/docs/ru/16-bake-cookbook.md +12 -6
  78. package/docs/ru/18-api-freeze-map.md +5 -3
  79. package/docs/ru/20-v1-stability.md +1 -1
  80. package/docs/uk/00-the-mado-way.md +70 -44
  81. package/docs/uk/01-routing.md +41 -47
  82. package/docs/uk/02-project-layout.md +68 -41
  83. package/docs/uk/03-static-bake.md +1 -2
  84. package/docs/uk/06-for-backenders.md +3 -3
  85. package/docs/uk/08-llm-zero-history-test.md +22 -24
  86. package/docs/uk/09-shadow-vs-light-dom.md +37 -86
  87. package/docs/uk/10-app-architecture.md +72 -31
  88. package/docs/uk/11-layouts.md +25 -12
  89. package/docs/uk/12-auth-and-api.md +58 -22
  90. package/docs/uk/13-deployment.md +4 -3
  91. package/docs/uk/14-testing.md +1 -1
  92. package/docs/uk/18-api-freeze-map.md +1 -1
  93. package/docs/uk/20-v1-stability.md +1 -1
  94. package/llms.txt +14 -15
  95. package/package.json +18 -11
  96. package/scripts/_config.mjs +15 -161
  97. package/scripts/bake.mjs +67 -57
  98. package/scripts/cli/generate.mjs +348 -0
  99. package/scripts/cli/help.mjs +27 -0
  100. package/scripts/cli/index.mjs +79 -0
  101. package/scripts/cli/init.mjs +153 -0
  102. package/scripts/cli/release.mjs +152 -0
  103. package/scripts/cli/run.mjs +96 -0
  104. package/scripts/cli.mjs +2 -621
  105. package/scripts/package-smoke.mjs +4 -1
  106. package/scripts/preview.mjs +13 -37
  107. package/scripts/size-budget.mjs +5 -2
  108. package/scripts/vite.default.mjs +11 -0
  109. package/starters/default/.editorconfig +12 -0
  110. package/starters/default/README.md +74 -0
  111. package/starters/default/eslint.config.mjs +256 -0
  112. package/starters/default/index.html +13 -0
  113. package/starters/default/package.json +30 -0
  114. package/starters/default/public/favicon.svg +4 -0
  115. package/starters/default/src/app.routes.ts +39 -0
  116. package/starters/default/src/layouts/app-shell.layout.ts +35 -0
  117. package/starters/default/src/layouts/auth-shell.layout.ts +17 -0
  118. package/starters/default/src/main.ts +16 -0
  119. package/starters/default/src/modules/auth/_contracts/auth-api.types.ts +17 -0
  120. package/starters/default/src/modules/auth/auth.connector.ts +45 -0
  121. package/starters/default/src/modules/auth/auth.guard.ts +22 -0
  122. package/starters/default/src/modules/auth/auth.public.ts +9 -0
  123. package/starters/default/src/modules/auth/auth.routes.ts +8 -0
  124. package/starters/default/src/modules/auth/auth.service.ts +71 -0
  125. package/starters/default/src/modules/auth/auth.types.ts +15 -0
  126. package/starters/default/src/modules/auth/login.page.ts +62 -0
  127. package/starters/default/src/modules/billing/_contracts/stripe.types.ts +17 -0
  128. package/starters/default/src/modules/billing/api/stripe.connector.ts +71 -0
  129. package/starters/default/src/modules/billing/billing.public.ts +5 -0
  130. package/starters/default/src/modules/billing/billing.routes.ts +9 -0
  131. package/starters/default/src/modules/billing/billing.types.ts +15 -0
  132. package/starters/default/src/modules/billing/components/invoice-status-badge.component.ts +43 -0
  133. package/starters/default/src/modules/billing/data/invoices.resource.ts +35 -0
  134. package/starters/default/src/modules/billing/pages/invoice-detail.page.ts +70 -0
  135. package/starters/default/src/modules/billing/pages/invoices-list.page.ts +73 -0
  136. package/starters/default/src/modules/home/home.page.ts +34 -0
  137. package/starters/default/src/modules/home/not-found.page.ts +11 -0
  138. package/starters/default/src/shared/http/http-client.ts +86 -0
  139. package/starters/default/src/shared/http/http-error.ts +37 -0
  140. package/starters/default/src/shared/http/interceptors.ts +59 -0
  141. package/starters/default/src/shared/lib/format-date.ts +19 -0
  142. package/starters/default/src/shared/styles/content.css +70 -0
  143. package/starters/default/src/shared/styles/reset.css +32 -0
  144. package/starters/default/src/shared/styles/shell.css +57 -0
  145. package/starters/default/src/shared/styles/tokens.css +44 -0
  146. package/starters/default/src/shared/ui/x-button.component.ts +49 -0
  147. package/starters/default/src/shared/ui/x-spinner.component.ts +22 -0
  148. package/starters/default/src/styles.d.ts +1 -0
  149. package/starters/default/src/vite-env.d.ts +1 -0
  150. package/starters/default/tsconfig.json +24 -0
  151. package/starters/default/vite.config.ts +9 -0
  152. package/MADO_V1_PLAN.md +0 -179
  153. package/ROADMAP.md +0 -178
  154. package/dist/src/html.d.ts +0 -18
  155. package/dist/src/html.js +0 -17
  156. package/dist/src/html.js.map +0 -1
  157. package/dist/src/router.d.ts +0 -13
  158. package/dist/src/router.js +0 -13
  159. package/dist/src/router.js.map +0 -1
  160. package/scripts/bundle.mjs +0 -212
  161. package/scripts/llm-zero-history-smoke.mjs +0 -93
  162. package/scripts/new.mjs +0 -80
  163. package/scripts/showcase-regression.mjs +0 -392
  164. package/server/serve.mjs +0 -455
  165. package/starters/admin/README.md +0 -63
  166. package/starters/admin/index.html +0 -28
  167. package/starters/admin/mado.config.json +0 -22
  168. package/starters/admin/package.json +0 -24
  169. package/starters/admin/public/favicon.svg +0 -4
  170. package/starters/admin/src/components/x-button.ts +0 -82
  171. package/starters/admin/src/components/x-input.ts +0 -105
  172. package/starters/admin/src/layouts/app.ts +0 -101
  173. package/starters/admin/src/layouts/auth.ts +0 -41
  174. package/starters/admin/src/lib/api.ts +0 -184
  175. package/starters/admin/src/lib/auth.ts +0 -83
  176. package/starters/admin/src/main.ts +0 -15
  177. package/starters/admin/src/pages/admin/dashboard.ts +0 -48
  178. package/starters/admin/src/pages/admin/order-detail.ts +0 -80
  179. package/starters/admin/src/pages/admin/orders.ts +0 -117
  180. package/starters/admin/src/pages/home.ts +0 -34
  181. package/starters/admin/src/pages/login.ts +0 -70
  182. package/starters/admin/src/pages/not-found.ts +0 -12
  183. package/starters/admin/src/routes.ts +0 -40
  184. package/starters/admin/src/styles/global.ts +0 -86
  185. package/starters/admin/tsconfig.json +0 -15
  186. package/starters/crud/README.md +0 -33
  187. package/starters/crud/index.html +0 -28
  188. package/starters/crud/mado.config.json +0 -20
  189. package/starters/crud/package.json +0 -24
  190. package/starters/crud/src/components/app-shell.ts +0 -56
  191. package/starters/crud/src/components/ticket-detail.ts +0 -33
  192. package/starters/crud/src/components/ticket-form.ts +0 -69
  193. package/starters/crud/src/components/ticket-list.ts +0 -66
  194. package/starters/crud/src/lib/api.ts +0 -76
  195. package/starters/crud/src/main.ts +0 -9
  196. package/starters/crud/src/pages/home.ts +0 -34
  197. package/starters/crud/src/pages/not-found.ts +0 -12
  198. package/starters/crud/src/pages/ticket-detail.ts +0 -7
  199. package/starters/crud/src/pages/ticket-new.ts +0 -7
  200. package/starters/crud/src/pages/tickets.ts +0 -7
  201. package/starters/crud/src/routes.ts +0 -11
  202. package/starters/crud/src/styles/global.ts +0 -155
  203. package/starters/crud/tsconfig.json +0 -15
  204. package/starters/minimal/README.md +0 -21
  205. package/starters/minimal/index.html +0 -28
  206. package/starters/minimal/mado.config.json +0 -20
  207. package/starters/minimal/package.json +0 -24
  208. package/starters/minimal/src/components/app-counter.ts +0 -31
  209. package/starters/minimal/src/main.ts +0 -9
  210. package/starters/minimal/src/pages/home.ts +0 -35
  211. package/starters/minimal/src/pages/not-found.ts +0 -14
  212. package/starters/minimal/src/routes.ts +0 -8
  213. package/starters/minimal/src/styles/global.ts +0 -60
  214. package/starters/minimal/tsconfig.json +0 -15
  215. package/templates/page-detail.ts +0 -63
  216. package/templates/page-form.ts +0 -94
  217. package/templates/page-list.ts +0 -79
@@ -3,118 +3,83 @@
3
3
  > Une seule bonne façon. Des contrats stricts. Pas de magie.
4
4
 
5
5
  Mado est un framework pour les équipes qui construisent des panneaux d'admin,
6
- des outils internes et des SPA métier des apps qui doivent être simples à
7
- créer et ennuyeuses à maintenir. Pour cela, il impose un **ensemble de
8
- conventions**. Si vous les respectez, le projet reste compréhensible même avec
9
- 200 écrans et 5 développeurs. Si vous les enfreignez — les types et le linter
10
- vous le diront immédiatement.
6
+ des outils internes et des SPA métier. Ces apps doivent être simples à créer
7
+ et ennuyeuses à maintenir. Mado préfère donc des conventions claires à cinq
8
+ styles équivalents.
11
9
 
12
10
  ## Principes
13
11
 
14
- 1. **Une seule voie.** Pour chaque tâche, il existe un seul chemin correct, pas cinq. Si vous
15
- écrivez quelque chose d'inhabituel demandez-vous si un helper idiomatique n'existe pas déjà.
16
- 2. **L'explicite plutôt que la magie.** Pas de scanners de système de fichiers, pas de globals
17
- implicites, pas d'effets de bord cachés. Tout ce que fait le framework peut être lu dans un
18
- seul fichier.
19
- 3. **La plateforme d'abord.** Si le navigateur propose déjà une fonctionnalité — utilisez-la
20
- directement. Pas d'abstractions personnalisées sur `fetch`, `<form>`, l'History API, ou
21
- Shadow DOM.
22
- 4. **Types stricts.** `tsc --strict --noUncheckedIndexedAccess` toujours. Si quelque chose ne
23
- peut pas être typé — c'est un signal que l'API est mauvaise.
24
- 5. **Pas de dépendances runtime.** Chaque dépendance est un engagement sur des années ;
25
- l'écosystème Web Components n'en a pas besoin.
12
+ 1. **Une seule voie.** Si vous écrivez quelque chose d'inhabituel, vérifiez
13
+ d'abord s'il existe déjà un helper/API canonique.
14
+ 2. **L'explicite plutôt que la magie.** Pas de file-system scanners, globals
15
+ implicites ou side effects cachés.
16
+ 3. **La plateforme d'abord.** Web Components, History API, `<form>`, `fetch` et
17
+ Shadow DOM restent visibles.
18
+ 4. **Types stricts.** `tsc --strict --noUncheckedIndexedAccess` toujours.
19
+ 5. **Pas de dépendances runtime.** Le tooling dev/build est acceptable ; le
20
+ runtime Mado reste natif.
26
21
 
27
- ## Conventions
22
+ ## Structure du projet
28
23
 
29
- ### Structure du projet
30
-
31
- ```
24
+ ```txt
32
25
  src/
33
- ├── routes.ts manifeste de routes, un fichier par projet
34
- ├── main.ts point d'entrée : providers + montage de <x-app>
35
- ├── pages/ une page = un fichier = `export default page({...})`
36
- ├── components/ composants réutilisables, enregistrement des effets de bord
37
- ├── lib/ contextes, clients API, logique métier sans UI
38
- └── styles/ ← styles partagés (si nécessaire), fichiers .ts avec css``
39
- ```
40
-
41
- C'est **obligatoire**, pas optionnel. Si un projet a 10 développeurs — ils doivent
42
- tous écrire de la même manière.
43
-
44
- ### Un composant = un fichier
45
-
46
- ```ts
47
- // src/components/user-card.ts
48
- import { component, html, css } from "@madojs/mado";
49
-
50
- component(
51
- "x-user-card",
52
- () => {
53
- return () => html`<div class="card"><slot /></div>`;
54
- },
55
- {
56
- styles: css`
57
- .card {
58
- padding: 1rem;
59
- }
60
- `,
61
- },
62
- );
26
+ ├── main.ts boot: global CSS/providers + render router
27
+ ├── app.routes.ts readable app map, exports `manifest` + default routes()
28
+ ├── layouts/ app-zone wrappers (`page({ view: ({ child }) => ... })`)
29
+ ├── shared/ UI bricks, http client, pure lib, global CSS
30
+ └── modules/ bounded contexts
31
+ └── billing/
32
+ ├── billing.routes.ts
33
+ ├── billing.public.ts
34
+ ├── billing.types.ts
35
+ ├── pages/
36
+ ├── data/
37
+ ├── api/
38
+ └── _contracts/
63
39
  ```
64
40
 
65
- `import './components/user-card.js'` **enregistre** le composant via
66
- `customElements.define`. C'est un effet de bord. Importez là où le composant est nécessaire.
67
-
68
- ### Une seule façon de charger les données
41
+ Le starter par défaut est la version canonique de cette forme. Si d'anciens
42
+ exemples divergent, le starter et `docs/10-app-architecture.md` gagnent.
69
43
 
70
- N'appelez pas `fetch()` directement depuis un composant. Utilisez toujours :
44
+ ## Un composant = un fichier
71
45
 
72
46
  ```ts
73
- // lecture resource
74
- const user = resource(() => `/api/users/${id()}`, jsonFetcher());
47
+ import { component, css, html } from "@madojs/mado";
75
48
 
76
- // écriture mutation
77
- const save = mutation(api.save, { invalidates: ["/api/users*"] });
49
+ component("x-user-card", () => () => html`<div class="card"><slot></slot></div>`, {
50
+ styles: css`
51
+ .card { padding: 1rem; }
52
+ `,
53
+ });
78
54
  ```
79
55
 
80
- Cela fournit la mise en cache, l'annulation, la gestion des erreurs et l'invalidation automatique.
56
+ Importer le fichier du composant enregistre l'élément. Importez-le le tag
57
+ est utilisé.
81
58
 
82
- ### Une seule façon de décrire une page
59
+ ## Une seule façon de décrire une page
83
60
 
84
61
  ```ts
85
- // src/pages/user-profile.ts
86
- import { page, html, resource, jsonFetcher } from "@madojs/mado";
62
+ import { html, page, resource, jsonFetcher } from "@madojs/mado";
87
63
 
88
64
  export default page({
89
- title: ({ id }) => `Utilisateur #${id}`,
90
- view: ({ params }) => html`...`,
65
+ title: ({ id }) => `User #${id}`,
66
+ view: ({ params }) => {
67
+ const user = resource(() => `/api/users/${params.id}`, jsonFetcher());
68
+ return html`...`;
69
+ },
91
70
  });
92
71
  ```
93
72
 
94
- Trois emplacements `title`, `load`, `view`. Pas d'autres. Vous voulez autre chose — c'est
95
- un composant ou un helper.
96
-
97
- ### Une seule façon de déclarer les routes
98
-
99
- Voir [`01-routing.md`](./01-routing.md).
100
-
101
- ## Ce que nous NE faisons PAS
102
-
103
- - ❌ N'écrivez pas de composants sans trait d'union. C'est la règle du navigateur pour
104
- les custom elements : `user-card` est correct, `usercard` ne l'est pas.
105
- - `x-*` n'est qu'une convention pour les exemples et les tests Mado, pas un standard de marque.
106
- En production, utilisez un préfixe de domaine : `app-*`, `crm-*`, `ticket-*`, `admin-*`.
107
- - ❌ N'utilisez pas `innerHTML` directement. Uniquement via `html\`\``.
108
- - ❌ N'appelez pas `setTimeout`/`setInterval` sans nettoyage. Uniquement à l'intérieur de `effect()`.
109
- - ❌ Ne stockez pas d'état mutable global. Utilisez les signals et `context`.
110
- - ❌ N'ajoutez pas de packages sans discussion. Chaque dépendance est un engagement.
111
-
112
- ## En cas de doute
73
+ Les signals, resources et forms locaux à une page vivent dans `view()`. L'état
74
+ partagé par un module vit dans `*.service.ts`.
113
75
 
114
- Si vous vous demandez "quelle est la meilleure façon ici ?" — c'est un signal que :
76
+ ## Ce que nous ne faisons pas
115
77
 
116
- 1. Soit il existe un helper intégré que vous ne connaissez pas (consultez `docs/`).
117
- 2. Soit c'est une nouvelle situation discutez-en et **consignez-la** dans ce document
118
- comme une convention supplémentaire.
78
+ - Pas de JSX/Vue/Svelte syntax.
79
+ - Pas de custom elements sans trait d'union.
80
+ - Pas de lecture de signal via `.value`; un signal est une fonction.
81
+ - Pas de `innerHTML` direct.
82
+ - Pas de runtime packages sans discussion.
119
83
 
120
- "Un 'bien' cohérent vaut mieux qu'un 'idéal' varié."
84
+ En cas de doute, documentez une recette claire plutôt que d'ajouter un nouveau
85
+ primitive au core.
@@ -1,202 +1,120 @@
1
1
  # Routage
2
2
 
3
- > Un seul fichier manifeste. Pas de scanners de dossiers. Pas de caractères spéciaux.
3
+ > Une seule app map. Pas de folder scanners. Pas de syntaxe magique.
4
4
 
5
- ## Pourquoi pas de routes basées sur les fichiers
5
+ Mado ne déduit pas les routes depuis les fichiers. La composition doit rester
6
+ lisible dans un seul endroit.
6
7
 
7
- Dans Next/SvelteKit/SolidStart, les routes apparaissent "magiquement" à partir des noms de
8
- fichiers. Cela a des avantages (la structure d'URL visible dans `pages/`), mais en production
9
- cela signifie :
8
+ ## App Manifest
10
9
 
11
- - Un plugin-scanner invisible dans le build. Sans lui, les fichiers ne sont que des fichiers.
12
- - Des caractères spéciaux dans les chemins : `[id]`, `(group)`, `_layout`, `+page.svelte`, `...slug`.
13
- - Les routes serveur et les routes client se mélangent.
14
- - Tester le routage est pénible : vous avez besoin d'un émulateur de build-tool.
15
-
16
- Mado considère cela comme **trop de magie**. Nous procédons différemment.
17
-
18
- ## Manifeste
19
-
20
- Un seul fichier — `src/routes.ts`. Un seul objet. Lu de haut en bas.
10
+ Utilisez `src/app.routes.ts` comme carte de l'application :
21
11
 
22
12
  ```ts
23
- // src/routes.ts
24
- import { routes } from '@madojs/mado';
25
-
26
- export default routes({
27
- '/': () => import('./pages/home.js'),
28
- '/about': () => import('./pages/about.js'),
29
- '/users/:id': () => import('./pages/user-profile.js'),
30
- '/users/:id/edit':() => import('./pages/user-edit.js'),
31
- '*': () => import('./pages/not-found.js'),
32
- });
13
+ import { layout, routes } from "@madojs/mado";
14
+ import { requireAuth } from "./modules/auth/auth.public";
15
+ import { authRoutes } from "./modules/auth/auth.routes";
16
+ import { billingRoutes } from "./modules/billing/billing.routes";
17
+
18
+ export const manifest = {
19
+ "/": () => import("./modules/home/home.page.js"),
20
+ "/login": layout({
21
+ layout: () => import("./layouts/auth-shell.layout.js"),
22
+ routes: authRoutes,
23
+ }),
24
+ "/billing": layout({
25
+ layout: () => import("./layouts/app-shell.layout.js"),
26
+ guard: requireAuth,
27
+ routes: billingRoutes,
28
+ }),
29
+ "*": () => import("./modules/home/not-found.page.js"),
30
+ };
31
+
32
+ export default routes(manifest);
33
33
  ```
34
34
 
35
- Vous voulez voir toutes les routes ? Ouvrez `routes.ts`. Pas de surprises.
35
+ Ouvrez `app.routes.ts` pour voir les zones de l'app : pages publiques, auth,
36
+ zones protégées, guards et shells.
36
37
 
37
- ## Ce qui va à droite d'un chemin
38
+ Exportez `manifest` pour `mado bake`.
38
39
 
39
- Chaque entrée est **l'une de ces trois choses** :
40
+ ## Module Routes
40
41
 
41
- ### 1. Import lazy (recommandé)
42
+ Les modules exportent de simples route maps. Ils n'appellent pas `layout()` et
43
+ ne décident pas quel shell les enveloppe.
42
44
 
43
45
  ```ts
44
- '/posts': () => import('./pages/posts.js'),
46
+ export const billingRoutes = {
47
+ "/invoices": () => import("./pages/invoices-list.page.js"),
48
+ "/invoices/:id": () => import("./pages/invoice-detail.page.js"),
49
+ };
45
50
  ```
46
51
 
47
- - Le navigateur crée son propre chunk lors du bundling (esbuild --bundle --splitting).
48
- - Le module est chargé uniquement quand l'utilisateur visite la route.
49
- - Les navigations suivantes utilisent le résultat mis en cache.
52
+ Le prefix est appliqué par `src/app.routes.ts` quand le module est monté sous
53
+ `"/billing"`.
50
54
 
51
- ### 2. Page prête (eager)
55
+ ## Layout Group
52
56
 
53
57
  ```ts
54
- import about from './pages/about.js';
55
-
56
- '/about': about,
58
+ "/admin": layout({
59
+ layout: () => import("./layouts/app-shell.layout.js"),
60
+ guard: requireAuth,
61
+ routes: adminRoutes,
62
+ }),
57
63
  ```
58
64
 
59
- Dans le bundle immédiatement, sans délai. Utilisez pour les pages critiques (accueil, connexion).
60
-
61
- ### 3. Imbriqué avec layout
65
+ Un layout est un fichier `page({...})` ordinaire :
62
66
 
63
67
  ```ts
64
- import { routes, nested } from '@madojs/mado';
65
-
66
- export default routes({
67
- '/': () => import('./pages/home.js'),
68
-
69
- '/admin/*': nested({
70
- layout: () => import('./layouts/admin.js'),
71
- routes: {
72
- '': () => import('./pages/admin/dashboard.js'),
73
- 'users': () => import('./pages/admin/users.js'),
74
- 'logs': () => import('./pages/admin/logs.js'),
75
- },
76
- }),
77
- });
78
- ```
79
-
80
- Un layout est juste une `page({...})` ordinaire qui rend `ctx.child` où elle le souhaite :
81
-
82
- ```ts
83
- // src/layouts/admin.ts
84
- import { page, html, css, component } from '@madojs/mado';
68
+ import { html, page } from "@madojs/mado";
85
69
 
86
70
  export default page({
87
71
  view: ({ child }) => html`
88
- <div class="admin">
89
- <aside><nav>...</nav></aside>
90
- <main>${child}</main>
72
+ <div class="layout layout--app">
73
+ <main class="app-main">${child}</main>
91
74
  </div>
92
75
  `,
93
76
  });
94
77
  ```
95
78
 
96
- ## Contrat de page
97
-
98
- ```ts
99
- import { page, html, resource, jsonFetcher } from '@madojs/mado';
100
-
101
- export default page({
102
- title: ({ id }) => `Utilisateur #${id}`, // string | (params) => string
103
- load: ({ id }) => resource(...), // optionnel, retourne Resource ou data
104
- view: ({ params, data, path, child }) => html`...`, // OBLIGATOIRE
105
- });
106
- ```
79
+ Gardez les layout views stateless. Les signals, resources et forms spécifiques
80
+ à une page vivent dans les pages/components/resources.
107
81
 
108
- Trois emplacements, c'est tout. Si vous exportez autre chose que `page({...})`, une simple
109
- fonction par exemple — `routes()` génère une erreur claire :
110
-
111
- ```
112
- [Mado] La route lazy n'a pas retourné page({...}) comme export par défaut.
113
- ```
114
-
115
- ## Paramètres d'URL
82
+ ## Page Contract
116
83
 
117
84
  ```ts
118
- '/users/:id': () => import('./pages/user.js'),
119
- ```
85
+ import { html, page } from "@madojs/mado";
120
86
 
121
- ```ts
122
87
  export default page<{ id: string }>({
123
- title: ({ id }) => `Utilisateur ${id}`,
124
- view: ({ params }) => html`<h1>${params.id}</h1>`,
88
+ title: ({ id }) => `User ${id}`,
89
+ view: ({ params }) => html`<h1>${params.id}</h1>`,
125
90
  });
126
91
  ```
127
92
 
128
- Les types sont passés dans `page<Params>` — `tsc` vérifie que vous n'accédez pas à
129
- `params.foo` qui n'existe pas dans la route.
130
-
131
- ## Options globales
132
-
133
- ```ts
134
- export default routes(
135
- { '/': home, '/about': about, '*': nf },
136
- {
137
- titleSuffix: ' · MonApp', // → "Accueil · MonApp"
138
- loading: () => html`<x-spinner/>`, // pendant le chargement du module
139
- error: (err) => html`<x-fatal-error .err=${err}/>`,
140
- },
141
- );
142
- ```
143
-
144
- ## Navigation programmatique
93
+ ## Navigation
145
94
 
146
95
  ```ts
147
- import route from './routes.js';
96
+ import appRoutes from "./app.routes.js";
148
97
 
149
- route.navigate('/posts');
150
- route.navigate('/posts?page=2');
151
- route.navigate('/posts', { replace: true });
98
+ appRoutes.navigate("/billing/invoices");
99
+ appRoutes.navigate("/billing/invoices?page=2");
100
+ appRoutes.navigate("/login", { replace: true });
152
101
  ```
153
102
 
154
- Les clics sur `<a href="/foo" data-link>` sont interceptés globalement (sans l'attribut —
155
- le navigateur effectue un rechargement complet, comme prévu pour les liens externes).
156
-
157
- ## Paramètres de requête
103
+ ## Query Parameters
158
104
 
159
105
  ```ts
160
- import { queryParam } from '@madojs/mado';
106
+ import { queryParam } from "@madojs/mado";
161
107
 
162
- const page = queryParam('page', '1');
163
- page(); // '1'
164
- page.set('2'); // history.replaceState + re-rendu
165
- page.set(null); // supprimer le paramètre
166
- page.set('3', { push: true }); // history.pushState
108
+ const page = queryParam("page", "1");
109
+ page();
110
+ page.set("2");
111
+ page.set(null);
112
+ page.set("3", { push: true });
167
113
  ```
168
114
 
169
- `queryParam` est un signal normal. Utilisez-le n'importe où : dans les pages, les composants,
170
- les computed.
171
-
172
- ## Ce qui est intentionnellement absent
173
-
174
- - ❌ Auto-scan de `pages/`. **Un seul fichier manifeste explicite**.
175
- - ❌ Caractères spéciaux dans les chemins (`[id]`, `(group)`, `_layout`). **Les paramètres sont
176
- uniquement `:name`, rien d'autre**.
177
- - ❌ Routage côté serveur dans le même manifeste. Mado est un framework côté client.
178
- - ❌ Auto-préchargement au survol. Si vous en avez vraiment besoin — faites-le manuellement :
179
- `link.addEventListener('mouseenter', loader)`. Généralement inutile.
180
-
181
- ## FAQ
182
-
183
- **Et si j'ai 100 routes ? Le fichier ne deviendra-t-il pas énorme ?**
184
- Il atteindra ~150 lignes. C'est toujours **une seule source de vérité** contre une centaine
185
- de fichiers dans `pages/` avec des noms magiques. En pratique, même les grands projets (1000+
186
- pages) peuvent se diviser en manifestes de fonctionnalités :
187
-
188
- ```ts
189
- import { routes } from '@madojs/mado';
190
- import adminRoutes from './features/admin/routes.js';
191
- import billingRoutes from './features/billing/routes.js';
192
-
193
- export default routes({
194
- ...adminRoutes,
195
- ...billingRoutes,
196
- '*': () => import('./pages/not-found.js'),
197
- });
198
- ```
115
+ ## Ce qui est absent volontairement
199
116
 
200
- **Comment tester le routage ?**
201
- Importez `routes.ts` c'est juste un objet. Substituez votre router mock. Pas besoin
202
- d'émulation de build-tool.
117
+ - Pas d'auto-scan des dossiers de pages.
118
+ - Pas de syntaxe filesystem comme `[id]`, `(group)`, `_layout`.
119
+ - Pas de server routes dans le manifest client.
120
+ - Pas de découverte cachée des layouts.
@@ -1,65 +1,84 @@
1
1
  # Structure du projet
2
2
 
3
- Chaque nouveau projet Mado a la même structure. C'est une convention **obligatoire**.
3
+ Chaque application Mado utilise la même forme canonique. Cette convention
4
+ permet aux humains et aux assistants IA de savoir où placer le code.
4
5
 
5
- ```
6
+ ```txt
6
7
  my-app/
7
8
  ├── package.json # runtime dep: @madojs/mado
8
9
  ├── tsconfig.json # strict TS, ES2022, Bundler resolution
9
- ├── mado.config.json # configuration dev/build/bake/bundle
10
- ├── index.html # shell SPA et template pour bake
11
- ├── public/ # assets statiques (favicon, images, robots.txt)
10
+ ├── vite.config.ts # mado() from @madojs/mado/vite
11
+ ├── index.html # entrée Vite + shell SPA
12
+ ├── public/ # assets statiques: favicon, images, robots.txt
12
13
  └── src/
13
- ├── main.ts # entrée : mount router dans #app
14
- ├── routes.ts # route manifest (default + named manifest)
15
- ├── pages/ # une page = un fichier = `export default page({...})`
16
- ├── components/ # composants réutilisables (x-*)
17
- ├── layouts/ # pages de layout (pour nested)
18
- └── lib/
19
- ├── api.ts # tous les wrappers fetch
20
- ├── contexts.ts # createContext(...)
21
- ├── theme.ts # thèmes
22
- └── ... # utilitaires, types, règles métier
14
+ ├── main.ts # importe le CSS et monte le router dans #app
15
+ ├── app.routes.ts # app map: manifest + default routes(...)
16
+ ├── layouts/ # layouts de zones d'application
17
+ ├── shared/ # ui, http, lib, styles
18
+ └── modules/ # bounded contexts
19
+ └── billing/
20
+ ├── billing.routes.ts
21
+ ├── billing.public.ts
22
+ ├── billing.types.ts
23
+ ├── pages/
24
+ ├── data/
25
+ ├── api/
26
+ └── _contracts/
23
27
  ```
24
28
 
25
29
  ## États Des Artefacts
26
30
 
27
31
  | Dossier | Ce que c'est | Écrit par | Déployer ? |
28
- |---|---|---|---|
32
+ | --- | --- | --- | --- |
29
33
  | `src/` | sources TypeScript | vous | non |
30
- | `dist/` | output `tsc`, native ESM pour dev | `mado build` | non |
31
- | `public/` | assets statiques écrits par vous | vous | via `out/` |
32
- | `out/` | artefact déployable : shell SPA + bundles + HTML baked promu | `mado release` | oui |
34
+ | `public/` | assets statiques copiés tels quels | vous | via `out/` |
35
+ | `out/` | artefact déployable: shell SPA + assets + HTML baked | `mado release` | oui |
36
+
37
+ `mado release` = `typecheck` + build Vite (`out/index.html`, `out/assets/`,
38
+ `public/*`) + `bake` directement dans les chemins de routes + `sitemap.xml` +
39
+ precompression.
33
40
 
34
- `mado release` = `typecheck` + `build` (`dist/`) + `bundle`
35
- (`out/assets/`) + `bake` (`out/baked/`) + promotion du HTML baked et de
36
- `sitemap.xml` dans les chemins déployables de `out/` + copie de `public/*`.
41
+ `index.html` reste à la racine car Vite le traite comme entry template. Mettez
42
+ dans `public/` uniquement les fichiers à copier tels quels.
37
43
 
38
44
  ## Où mettre un nouveau fichier ?
39
45
 
40
46
  | Quoi | Où |
41
- |---|---|
42
- | Page pour une nouvelle URL | `src/pages/foo.ts` + ajouter à `src/routes.ts` |
43
- | Widget UI réutilisable | `src/components/foo-bar.ts` |
44
- | Wrapper API | `src/lib/api.ts` (ajouter une méthode) |
45
- | Contexte global (thème, utilisateur, i18n) | `src/lib/<nom>.ts` |
46
- | Fonction pure sans UI | `src/lib/util/<nom>.ts` |
47
+ | --- | --- |
48
+ | Page pour une nouvelle URL | `src/modules/<module>/pages/<name>.page.ts` + module routes |
49
+ | Route map de module | `src/modules/<module>/<module>.routes.ts` |
50
+ | App shell/layout | `src/layouts/<zone>.layout.ts` |
51
+ | Widget UI partagé | `src/shared/ui/<x-name>.component.ts` |
52
+ | Widget UI propre à un module | `src/modules/<module>/components/<name>.component.ts` |
53
+ | API connector | `src/modules/<module>/api/<provider>.connector.ts` |
54
+ | Data resource/mutation | `src/modules/<module>/data/<name>.resource.ts` |
55
+ | Auth/session | `src/modules/auth/` |
56
+ | Surface publique de module | `src/modules/<module>/<module>.public.ts` |
57
+ | Fonction pure sans UI | `src/shared/lib/<name>.ts` |
58
+ | Image statique / favicon | `public/<file>` |
59
+ | CSS de shell | `src/shared/styles/shell.css` |
60
+ | CSS de contenu page | `src/shared/styles/content.css` |
47
61
 
48
- Si vous ne savez pas où — c'est un signal que **l'architecture souffre**.
49
- Consultez l'équipe, **consignez** la réponse dans `docs/`.
62
+ ## Vite Config
50
63
 
51
- ## Règles de nommage
64
+ ```ts
65
+ import { defineConfig } from "vite";
66
+ import { mado } from "@madojs/mado/vite";
67
+
68
+ export default defineConfig({
69
+ plugins: [mado()],
70
+ css: {
71
+ transformer: "lightningcss",
72
+ },
73
+ });
74
+ ```
52
75
 
53
- | Quoi | Style | Exemple |
54
- |---|---|---|
55
- | Fichier | kebab-case | `user-profile.ts` |
56
- | Tag de composant | `x-` + kebab | `<x-user-profile>` |
57
- | Context | PascalCase + `Ctx` | `ThemeCtx`, `AuthCtx` |
58
- | Signal | camelCase | `userId`, `isLoggedIn` |
59
- | Fonction de page (composant interne) | `x-<route>-page` | `<x-posts-page>` |
76
+ Le starter active le transformer Lightning CSS de Vite. Mado ne possède pas le
77
+ prefixing, le lowering CSS ou la minification.
60
78
 
61
- ## Ce qui ne va PAS dans src/
79
+ ## Ce qui ne va PAS dans `src/`
62
80
 
63
- - Configurations de build-tool (webpack, rollup, vite) nous n'en avons pas.
64
- - Fichiers `.env` — les variables d'environnement sont lues depuis `process.env`/`import.meta.env` dans `lib/config.ts`.
65
- - ❌ Tests mélangés avec le code — tout dans `test/`.
81
+ - Configs de build-tool supplémentairesutilisez `vite.config.ts`.
82
+ - Fichiers `.env` — lisez l'env dans `src/shared/lib/config.ts` puis importez
83
+ ce module.
84
+ - Tests mélangés au code — gardez-les dans `test/`.
@@ -163,7 +163,7 @@ out/
163
163
  {"slug":"mado-mug","name":"Mado Mug","price":12,"..."}
164
164
  </script>
165
165
 
166
- <script type="module" src="/dist/examples/main.js"></script>
166
+ <script type="module" src="/assets/main-abc123.js"></script>
167
167
  </body>
168
168
  ```
169
169
 
@@ -31,11 +31,11 @@ Si votre cas ne tombe pas dans le dernier point — Mado n'est probablement pas
31
31
  | Taille | ~6 Ko | ~16 Ko |
32
32
  | Âge / support | ~10 ans, Google | 6 mois, auteur unique |
33
33
  | Réactivité | décorateurs `@property` + `requestUpdate` manuel | signals (`signal`/`computed`/`effect`) intégrés |
34
- | Router | aucun, vous devez en trouver un (`@lit-labs/router`, etc.) | inclus : `routes()` + nested + prefetch + sync-cache |
34
+ | Router | aucun, vous devez en trouver un (`@lit-labs/router`, etc.) | inclus : `routes()` + layout groups + prefetch |
35
35
  | Chargement de données | aucun, vous devez l'assembler | `resource()` + `mutation()` + invalidation glob |
36
36
  | Forms | aucun | `useForm()` avec contraintes proches du HTML |
37
37
  | SEO / statique | complexe (`@lit-labs/ssr`) | `bake` (linkedom) + edge-prerender |
38
- | Build | nécessite esbuild/rollup/webpack | `tsc` suffit |
38
+ | Build | nécessite des plugins spécifiques au framework | Vite transport + runtime natif |
39
39
  | Style de code | classes + décorateurs | fonctions + tagged templates |
40
40
  | Écosystème | réel (Shoelace, Material Web, etc.) | aucun |
41
41
  | Quand choisir | écrire un design system / bibliothèque Web Components pour l'intégration | écrire une application complète, vouloir tout dans une boîte |
@@ -55,14 +55,14 @@ Si votre cas ne tombe pas dans le dernier point — Mado n'est probablement pas
55
55
  | Réactivité | signals (même classe d'idées) | signals |
56
56
  | Templates | JSX (compilé en expressions réactives) | tagged template `html\`\`` |
57
57
  | Modèle de composant | fonctions, nœuds virtuels Solid | Web Components |
58
- | Build | Vite + babel-plugin-solid requis | `tsc` uniquement |
58
+ | Build | Vite + babel-plugin-solid requis | Vite pour dev/build, aucune dépendance runtime |
59
59
  | Router | `@solidjs/router` | inclus |
60
60
  | Données | `createResource` | `resource()` |
61
61
  | SSR | sérieusement supporté (SolidStart) | intentionnellement absent |
62
62
  | Écosystème | en croissance, ~50 packages | aucun |
63
- | Quand choisir | besoin de top performance + JSX + prêt à configurer le build | vouloir tourner sans build / infrastructure minimale |
63
+ | Quand choisir | besoin de top performance + JSX + prêt à configurer le build | vouloir un runtime browser-native avec tooling simple |
64
64
 
65
- **Pitch honnête :** *"Solid est techniquement plus rapide et plus mature. Mais Solid nécessite Vite + un plugin babel. Mado ne nécessite rien d'autre que `tsc` c'est 'ouvrir VS Code, F5, et travailler'. Si cette différence n'est pas critique allez avec Solid."*
65
+ **Pitch honnête :** *"Solid est techniquement plus rapide et plus mature. Mado est plus simple dans son idée : runtime browser-native, Web Components, tagged templates, et Vite fait le travail dev/build ennuyeux. Si vous voulez JSX et un écosystème plus large, allez avec Solid."*
66
66
 
67
67
  ---
68
68
 
@@ -153,7 +153,7 @@ Je ne vais pas m'étendre là-dessus longtemps, car React est dans une **catégo
153
153
 
154
154
  Pas la taille, pas la performance, pas les signals — tout a de meilleurs concurrents.
155
155
 
156
- > **"Ouvrez le source et lisez-le en une soirée. ~3500 lignes, 12 modules. Si quelque chose casse — vous n'allez pas sur une issue avec 3000 commentaires. Vous allez dans `src/router.ts` et lisez 500 lignes."**
156
+ > **"Ouvrez le source et lisez-le en une soirée. ~3500 lignes, petits modules. Si quelque chose casse — vous n'allez pas sur une issue avec 3000 commentaires. Vous allez dans `src/router/` et lisez le code."**
157
157
 
158
158
  C'est ce qu'on appelle la **propriété** — vous possédez le code, plutôt que de dépendre de celui de quelqu'un d'autre.
159
159