@madojs/mado 0.5.1 → 0.6.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 (101) hide show
  1. package/AGENTS.md +26 -0
  2. package/CHANGELOG.md +153 -0
  3. package/MADO_V1_PLAN.md +179 -0
  4. package/README.md +31 -13
  5. package/ROADMAP.md +28 -7
  6. package/TODO.md +72 -0
  7. package/dist/src/forms.d.ts +37 -4
  8. package/dist/src/forms.js +331 -57
  9. package/dist/src/forms.js.map +1 -1
  10. package/dist/src/html/bindings.d.ts +41 -0
  11. package/dist/src/html/bindings.js +163 -6
  12. package/dist/src/html/bindings.js.map +1 -1
  13. package/dist/src/html.d.ts +2 -0
  14. package/dist/src/html.js +1 -0
  15. package/dist/src/html.js.map +1 -1
  16. package/dist/src/index.d.ts +6 -6
  17. package/dist/src/index.js +2 -2
  18. package/dist/src/index.js.map +1 -1
  19. package/dist/src/page.d.ts +56 -0
  20. package/dist/src/page.js +17 -0
  21. package/dist/src/page.js.map +1 -1
  22. package/dist/src/router/manifest.d.ts +16 -1
  23. package/dist/src/router/manifest.js +181 -38
  24. package/dist/src/router/manifest.js.map +1 -1
  25. package/dist/src/router/match.d.ts +7 -2
  26. package/dist/src/router/match.js +14 -4
  27. package/dist/src/router/match.js.map +1 -1
  28. package/dist/src/router/navigation.d.ts +10 -0
  29. package/dist/src/router/navigation.js +71 -3
  30. package/dist/src/router/navigation.js.map +1 -1
  31. package/dist/src/signal.d.ts +15 -1
  32. package/dist/src/signal.js +112 -16
  33. package/dist/src/signal.js.map +1 -1
  34. package/docs/en/02-project-layout.md +99 -40
  35. package/docs/en/10-app-architecture.md +141 -0
  36. package/docs/en/11-layouts.md +115 -0
  37. package/docs/en/12-auth-and-api.md +217 -0
  38. package/docs/en/13-deployment.md +192 -0
  39. package/docs/en/14-testing.md +82 -0
  40. package/docs/en/15-error-handling.md +100 -0
  41. package/docs/en/16-bake-cookbook.md +93 -0
  42. package/docs/en/README.md +7 -0
  43. package/docs/fr/10-app-architecture.md +61 -0
  44. package/docs/fr/11-layouts.md +35 -0
  45. package/docs/fr/12-auth-and-api.md +35 -0
  46. package/docs/fr/13-deployment.md +39 -0
  47. package/docs/fr/14-testing.md +41 -0
  48. package/docs/fr/15-error-handling.md +50 -0
  49. package/docs/fr/16-bake-cookbook.md +35 -0
  50. package/docs/fr/README.md +7 -0
  51. package/docs/ru/10-app-architecture.md +100 -0
  52. package/docs/ru/11-layouts.md +47 -0
  53. package/docs/ru/12-auth-and-api.md +53 -0
  54. package/docs/ru/13-deployment.md +60 -0
  55. package/docs/ru/14-testing.md +50 -0
  56. package/docs/ru/15-error-handling.md +56 -0
  57. package/docs/ru/16-bake-cookbook.md +55 -0
  58. package/docs/ru/README.md +7 -0
  59. package/docs/uk/10-app-architecture.md +56 -0
  60. package/docs/uk/11-layouts.md +34 -0
  61. package/docs/uk/12-auth-and-api.md +34 -0
  62. package/docs/uk/13-deployment.md +39 -0
  63. package/docs/uk/14-testing.md +34 -0
  64. package/docs/uk/15-error-handling.md +32 -0
  65. package/docs/uk/16-bake-cookbook.md +36 -0
  66. package/docs/uk/README.md +7 -0
  67. package/llms.txt +9 -1
  68. package/package.json +3 -1
  69. package/scripts/_config.mjs +224 -0
  70. package/scripts/bake.mjs +217 -120
  71. package/scripts/bundle.mjs +110 -67
  72. package/scripts/cli.mjs +119 -15
  73. package/scripts/preview.mjs +22 -12
  74. package/server/serve.mjs +82 -4
  75. package/starters/admin/README.md +63 -0
  76. package/starters/admin/index.html +21 -0
  77. package/starters/admin/mado.config.json +22 -0
  78. package/starters/admin/package.json +22 -0
  79. package/starters/admin/public/favicon.svg +4 -0
  80. package/starters/admin/src/components/x-button.ts +55 -0
  81. package/starters/admin/src/components/x-input.ts +74 -0
  82. package/starters/admin/src/layouts/app.ts +101 -0
  83. package/starters/admin/src/layouts/auth.ts +41 -0
  84. package/starters/admin/src/lib/api.ts +133 -0
  85. package/starters/admin/src/lib/auth.ts +83 -0
  86. package/starters/admin/src/main.ts +15 -0
  87. package/starters/admin/src/pages/admin/dashboard.ts +48 -0
  88. package/starters/admin/src/pages/admin/order-detail.ts +78 -0
  89. package/starters/admin/src/pages/admin/orders.ts +117 -0
  90. package/starters/admin/src/pages/home.ts +25 -0
  91. package/starters/admin/src/pages/login.ts +70 -0
  92. package/starters/admin/src/pages/not-found.ts +12 -0
  93. package/starters/admin/src/routes.ts +40 -0
  94. package/starters/admin/src/styles/global.ts +86 -0
  95. package/starters/admin/tsconfig.json +15 -0
  96. package/starters/crud/mado.config.json +20 -0
  97. package/starters/crud/package.json +8 -4
  98. package/starters/crud/src/routes.ts +4 -2
  99. package/starters/minimal/mado.config.json +20 -0
  100. package/starters/minimal/package.json +7 -3
  101. package/starters/minimal/src/routes.ts +4 -2
@@ -0,0 +1,78 @@
1
+ // Order detail page. Reads :id from params, fetches the order, and shows
2
+ // inline loading/error/empty/ready states.
3
+
4
+ import { html, jsonFetcher, page, resource } from "@madojs/mado";
5
+
6
+ interface OrderDetail {
7
+ id: string;
8
+ customer: string;
9
+ total: number;
10
+ status: string;
11
+ items: Array<{ sku: string; name: string; qty: number; price: number }>;
12
+ }
13
+
14
+ export default page<{ id: string }>({
15
+ title: ({ id }) => `Order ${id}`,
16
+ view: ({ params }) => {
17
+ const order = resource(
18
+ () => `/api/admin/orders/${params.id}`,
19
+ jsonFetcher<OrderDetail>(),
20
+ { staleTime: 15_000 },
21
+ );
22
+
23
+ return html`
24
+ <p>
25
+ <a href="/admin/orders" data-link>← All orders</a>
26
+ </p>
27
+ ${() => {
28
+ if (order.loading() && !order.data())
29
+ return html`<p class="muted">Loading order…</p>`;
30
+ if (order.error())
31
+ return html`<p style="color:var(--danger);">${order.error()?.message}</p>`;
32
+ const o = order.data();
33
+ if (!o)
34
+ return html`<p class="muted">Order not found.</p>`;
35
+ return html`
36
+ <h1 style="margin:0 0 8px;">Order ${o.id}</h1>
37
+ <p class="muted" style="margin:0 0 24px;">${o.customer} · ${o.status}</p>
38
+ <div class="card">
39
+ <table style="width:100%;border-collapse:collapse;">
40
+ <thead>
41
+ <tr style="text-align:left;border-bottom:1px solid var(--border);">
42
+ <th style="padding:8px 0;">SKU</th>
43
+ <th style="padding:8px 0;">Item</th>
44
+ <th style="padding:8px 0;text-align:right;">Qty</th>
45
+ <th style="padding:8px 0;text-align:right;">Price</th>
46
+ </tr>
47
+ </thead>
48
+ <tbody>
49
+ ${o.items.map(
50
+ (it) => html`
51
+ <tr style="border-bottom:1px solid var(--border);">
52
+ <td style="padding:8px 0;">${it.sku}</td>
53
+ <td style="padding:8px 0;">${it.name}</td>
54
+ <td style="padding:8px 0;text-align:right;">${it.qty}</td>
55
+ <td style="padding:8px 0;text-align:right;font-variant-numeric:tabular-nums;">
56
+ $${it.price.toFixed(2)}
57
+ </td>
58
+ </tr>
59
+ `,
60
+ )}
61
+ </tbody>
62
+ <tfoot>
63
+ <tr>
64
+ <td colspan="3" style="padding-top:12px;text-align:right;font-weight:600;">
65
+ Total
66
+ </td>
67
+ <td style="padding-top:12px;text-align:right;font-weight:600;font-variant-numeric:tabular-nums;">
68
+ $${o.total.toFixed(2)}
69
+ </td>
70
+ </tr>
71
+ </tfoot>
72
+ </table>
73
+ </div>
74
+ `;
75
+ }}
76
+ `;
77
+ },
78
+ });
@@ -0,0 +1,117 @@
1
+ // Orders list. Demonstrates queryParam() filters and each() keyed table rows.
2
+
3
+ import {
4
+ each,
5
+ html,
6
+ jsonFetcher,
7
+ page,
8
+ queryParam,
9
+ resource,
10
+ } from "@madojs/mado";
11
+
12
+ interface Order {
13
+ id: string;
14
+ customer: string;
15
+ total: number;
16
+ status: "open" | "paid" | "shipped" | "cancelled";
17
+ }
18
+
19
+ export default page({
20
+ title: "Orders",
21
+ view: () => {
22
+ const status = queryParam("status", "");
23
+ const search = queryParam("q", "");
24
+
25
+ const orders = resource(
26
+ () => {
27
+ const params = new URLSearchParams();
28
+ if (status()) params.set("status", status());
29
+ if (search()) params.set("q", search());
30
+ const qs = params.toString();
31
+ return `/api/admin/orders${qs ? `?${qs}` : ""}`;
32
+ },
33
+ jsonFetcher<Order[]>(),
34
+ { staleTime: 5_000 },
35
+ );
36
+
37
+ return html`
38
+ <header style="display:flex;align-items:center;gap:var(--space-3);margin:0 0 16px;">
39
+ <h1 style="margin:0;">Orders</h1>
40
+ <span class="spacer"></span>
41
+ <input
42
+ type="search"
43
+ placeholder="Search…"
44
+ .value=${search}
45
+ @input=${(e: Event) => {
46
+ const t = e.target as HTMLInputElement;
47
+ search.set(t.value);
48
+ }}
49
+ style="padding:6px 10px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg);color:var(--fg);"
50
+ >
51
+ <select
52
+ .value=${status}
53
+ @change=${(e: Event) => {
54
+ const t = e.target as HTMLSelectElement;
55
+ status.set(t.value);
56
+ }}
57
+ style="padding:6px 10px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg);color:var(--fg);"
58
+ >
59
+ <option value="">All statuses</option>
60
+ <option value="open">Open</option>
61
+ <option value="paid">Paid</option>
62
+ <option value="shipped">Shipped</option>
63
+ <option value="cancelled">Cancelled</option>
64
+ </select>
65
+ </header>
66
+
67
+ <div class="card" style="padding:0;overflow:hidden;">
68
+ ${() => {
69
+ if (orders.loading() && !orders.data())
70
+ return html`<p class="muted" style="padding:16px;">Loading…</p>`;
71
+ if (orders.error())
72
+ return html`<p style="color:var(--danger);padding:16px;">
73
+ ${orders.error()?.message}
74
+ </p>`;
75
+ const list = orders.data() ?? [];
76
+ if (list.length === 0)
77
+ return html`<p class="muted" style="padding:24px;text-align:center;">
78
+ No orders match the current filters.
79
+ </p>`;
80
+ return html`
81
+ <table style="width:100%;border-collapse:collapse;">
82
+ <thead>
83
+ <tr style="text-align:left;border-bottom:1px solid var(--border);">
84
+ <th style="padding:10px 14px;">ID</th>
85
+ <th style="padding:10px 14px;">Customer</th>
86
+ <th style="padding:10px 14px;">Status</th>
87
+ <th style="padding:10px 14px;text-align:right;">Total</th>
88
+ </tr>
89
+ </thead>
90
+ <tbody>
91
+ ${() =>
92
+ each(
93
+ list,
94
+ (o) => o.id,
95
+ (o) => html`
96
+ <tr style="border-bottom:1px solid var(--border);">
97
+ <td style="padding:10px 14px;">
98
+ <a href="/admin/orders/${o.id}" data-link>${o.id}</a>
99
+ </td>
100
+ <td style="padding:10px 14px;">${o.customer}</td>
101
+ <td style="padding:10px 14px;">
102
+ <span class="muted">${o.status}</span>
103
+ </td>
104
+ <td style="padding:10px 14px;text-align:right;font-variant-numeric:tabular-nums;">
105
+ $${o.total.toFixed(2)}
106
+ </td>
107
+ </tr>
108
+ `,
109
+ )}
110
+ </tbody>
111
+ </table>
112
+ `;
113
+ }}
114
+ </div>
115
+ `;
116
+ },
117
+ });
@@ -0,0 +1,25 @@
1
+ // Public landing page. Demonstrates that the marketing surface can live
2
+ // alongside the admin app without a guard, and can be baked for SEO.
3
+
4
+ import { html, page } from "@madojs/mado";
5
+
6
+ export default page({
7
+ title: "Welcome",
8
+ head: () => ({
9
+ description: "An admin app scaffold built with Mado.",
10
+ og: {
11
+ title: "__APP_NAME__",
12
+ description: "An admin app scaffold built with Mado.",
13
+ type: "website",
14
+ },
15
+ }),
16
+ view: () => html`
17
+ <main style="max-width:720px;margin:0 auto;padding:64px 24px;">
18
+ <h1>__APP_NAME__</h1>
19
+ <p>This is the public landing page.</p>
20
+ <p>
21
+ <a href="/admin" data-link>Open the admin app →</a>
22
+ </p>
23
+ </main>
24
+ `,
25
+ });
@@ -0,0 +1,70 @@
1
+ // Login page. Reads `?return=` to bounce the user back where they were
2
+ // blocked by `requireAuth`.
3
+
4
+ import { html, navigate, page, queryParam, signal, useForm } from "@madojs/mado";
5
+ import { ApiError } from "../lib/api.js";
6
+ import { login } from "../lib/auth.js";
7
+ import "../components/x-input.js";
8
+ import "../components/x-button.js";
9
+
10
+ export default page({
11
+ title: "Sign in",
12
+ view: () => {
13
+ const returnTo = queryParam("return", "/admin");
14
+ const serverError = signal<string | null>(null);
15
+
16
+ const form = useForm({
17
+ email: { required: true, type: "email" as const },
18
+ password: { required: true, min: 4 },
19
+ });
20
+
21
+ const onSubmit = form.onSubmit(async (values) => {
22
+ serverError.set(null);
23
+ try {
24
+ await login({
25
+ email: String(values.email ?? ""),
26
+ password: String(values.password ?? ""),
27
+ });
28
+ navigate(returnTo(), { replace: true });
29
+ } catch (e) {
30
+ if (e instanceof ApiError && e.status === 401) {
31
+ serverError.set("Invalid email or password.");
32
+ } else {
33
+ serverError.set("Something went wrong. Try again.");
34
+ }
35
+ }
36
+ });
37
+
38
+ return html`
39
+ <h1 style="margin:0 0 16px;">Sign in</h1>
40
+ <p class="muted" style="margin:0 0 24px;">
41
+ Enter your credentials to continue.
42
+ </p>
43
+ <form @submit=${onSubmit} class="stack">
44
+ <x-input
45
+ label="Email"
46
+ name="email"
47
+ type="email"
48
+ required
49
+ @input=${form.onInput}
50
+ @blur=${form.onBlur}
51
+ ></x-input>
52
+ <x-input
53
+ label="Password"
54
+ name="password"
55
+ type="password"
56
+ required
57
+ @input=${form.onInput}
58
+ @blur=${form.onBlur}
59
+ ></x-input>
60
+ ${() =>
61
+ serverError()
62
+ ? html`<small style="color:var(--danger);">${serverError()}</small>`
63
+ : null}
64
+ <x-button
65
+ ?disabled=${() => !form.isValid() || form.submitting()}
66
+ >${() => (form.submitting() ? "Signing in…" : "Sign in")}</x-button>
67
+ </form>
68
+ `;
69
+ },
70
+ });
@@ -0,0 +1,12 @@
1
+ import { html, page } from "@madojs/mado";
2
+
3
+ export default page({
4
+ title: "Not found",
5
+ view: () => html`
6
+ <main style="max-width:560px;margin:0 auto;padding:80px 24px;text-align:center;">
7
+ <h1 style="margin:0 0 12px;">404</h1>
8
+ <p class="muted">This page does not exist.</p>
9
+ <p><a href="/" data-link>← Back home</a></p>
10
+ </main>
11
+ `,
12
+ });
@@ -0,0 +1,40 @@
1
+ // The blessed routes manifest for an admin app.
2
+ //
3
+ // "/" → public landing
4
+ // "/login" → centered auth layout
5
+ // "/admin/*" → admin shell with sidebar/topbar, guarded by requireAuth
6
+ // "*" → 404
7
+ //
8
+ // Layouts and guards live inside the layout() blocks. There is exactly one
9
+ // canonical place to put a shell: a layout() in this manifest. Do not wrap
10
+ // route output in main.ts or in custom-element wrappers — that path causes
11
+ // the "shell-below-content" bug described in the v1 plan.
12
+ //
13
+ // Bake: `manifest` is exported separately for `mado bake` to discover pages
14
+ // that declare `bake: { paths, data }`. Without this named export `mado bake`
15
+ // fails with a clear error.
16
+
17
+ import { layout, routes } from "@madojs/mado";
18
+ import { requireAuth } from "./lib/auth.js";
19
+
20
+ export const manifest = {
21
+ "/": () => import("./pages/home.js"),
22
+ "/login": layout({
23
+ layout: () => import("./layouts/auth.js"),
24
+ routes: {
25
+ "/": () => import("./pages/login.js"),
26
+ },
27
+ }),
28
+ "/admin": layout({
29
+ layout: () => import("./layouts/app.js"),
30
+ guard: requireAuth,
31
+ routes: {
32
+ "/": () => import("./pages/admin/dashboard.js"),
33
+ "/orders": () => import("./pages/admin/orders.js"),
34
+ "/orders/:id": () => import("./pages/admin/order-detail.js"),
35
+ },
36
+ }),
37
+ "*": () => import("./pages/not-found.js"),
38
+ };
39
+
40
+ export default routes(manifest);
@@ -0,0 +1,86 @@
1
+ // Global design tokens + a tiny utility layer for admin UIs.
2
+ //
3
+ // Tokens are CSS custom properties on :root so layouts and components can pick
4
+ // them up without a CSS preprocessor. Light/dark via prefers-color-scheme.
5
+ //
6
+ // Keep this file intentionally small. Components should style themselves with
7
+ // Shadow DOM. Light DOM utilities (.row, .stack, .card) are here only because
8
+ // they show up in every admin page and would be noisy to redefine per component.
9
+
10
+ const css = `
11
+ :root {
12
+ color-scheme: light dark;
13
+
14
+ --bg: #ffffff;
15
+ --bg-elevated: #f7f8fa;
16
+ --fg: #0f172a;
17
+ --fg-muted: #475569;
18
+ --border: #e2e8f0;
19
+ --accent: #1f6feb;
20
+ --accent-fg: #ffffff;
21
+ --danger: #b91c1c;
22
+ --success: #15803d;
23
+
24
+ --radius: 8px;
25
+ --radius-sm: 6px;
26
+ --space-1: 4px;
27
+ --space-2: 8px;
28
+ --space-3: 12px;
29
+ --space-4: 16px;
30
+ --space-5: 24px;
31
+ --space-6: 32px;
32
+
33
+ --font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI",
34
+ Roboto, Inter, Helvetica, Arial, sans-serif;
35
+
36
+ --shadow-1: 0 1px 2px rgba(15, 23, 42, .05),
37
+ 0 1px 1px rgba(15, 23, 42, .04);
38
+ }
39
+
40
+ @media (prefers-color-scheme: dark) {
41
+ :root {
42
+ --bg: #0b1220;
43
+ --bg-elevated: #111a2e;
44
+ --fg: #e6eefc;
45
+ --fg-muted: #9aa6bd;
46
+ --border: #1f2a44;
47
+ --accent: #3b82f6;
48
+ --accent-fg: #0b1220;
49
+ }
50
+ }
51
+
52
+ * { box-sizing: border-box; }
53
+ html, body { margin: 0; padding: 0; }
54
+ body {
55
+ background: var(--bg);
56
+ color: var(--fg);
57
+ font-family: var(--font-sans);
58
+ font-size: 14px;
59
+ line-height: 1.5;
60
+ min-height: 100vh;
61
+ }
62
+
63
+ a { color: var(--accent); text-decoration: none; }
64
+ a:hover { text-decoration: underline; }
65
+
66
+ .row { display: flex; align-items: center; gap: var(--space-3); }
67
+ .stack { display: flex; flex-direction: column; gap: var(--space-3); }
68
+ .spacer { flex: 1; }
69
+
70
+ .card {
71
+ background: var(--bg-elevated);
72
+ border: 1px solid var(--border);
73
+ border-radius: var(--radius);
74
+ padding: var(--space-5);
75
+ box-shadow: var(--shadow-1);
76
+ }
77
+
78
+ .muted { color: var(--fg-muted); }
79
+ `;
80
+
81
+ if (typeof document !== "undefined" && !document.getElementById("admin-global-style")) {
82
+ const tag = document.createElement("style");
83
+ tag.id = "admin-global-style";
84
+ tag.textContent = css;
85
+ document.head.appendChild(tag);
86
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022", "DOM"],
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": "src",
11
+ "declaration": false,
12
+ "sourceMap": true
13
+ },
14
+ "include": ["src/**/*.ts"]
15
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "dev": {
3
+ "port": 5173,
4
+ "proxy": {}
5
+ },
6
+ "build": {
7
+ "out": "out",
8
+ "dist": "dist",
9
+ "publicDir": "public"
10
+ },
11
+ "bake": {
12
+ "entry": "src/routes.ts",
13
+ "template": "index.html",
14
+ "baseUrl": "https://example.com"
15
+ },
16
+ "bundle": {
17
+ "splitting": true,
18
+ "compress": ["gz", "br"]
19
+ }
20
+ }
@@ -4,10 +4,14 @@
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
7
- "build": "tsc -p tsconfig.json",
8
- "typecheck": "tsc -p tsconfig.json --noEmit",
7
+ "build": "mado build",
8
+ "typecheck": "mado typecheck",
9
+ "dev": "mado dev",
9
10
  "serve": "mado serve",
10
- "dev": "mado dev"
11
+ "bundle": "mado bundle",
12
+ "bake": "mado bake",
13
+ "release": "mado release",
14
+ "preview": "mado preview"
11
15
  },
12
16
  "dependencies": {
13
17
  "@madojs/mado": "__MADOJS_VERSION__"
@@ -15,4 +19,4 @@
15
19
  "devDependencies": {
16
20
  "typescript": "^6.0.3"
17
21
  }
18
- }
22
+ }
@@ -1,9 +1,11 @@
1
1
  import { routes } from "@madojs/mado";
2
2
 
3
- export default routes({
3
+ export const manifest = {
4
4
  "/": () => import("./pages/home.js"),
5
5
  "/tickets": () => import("./pages/tickets.js"),
6
6
  "/tickets/new": () => import("./pages/ticket-new.js"),
7
7
  "/tickets/:id": () => import("./pages/ticket-detail.js"),
8
8
  "*": () => import("./pages/not-found.js"),
9
- });
9
+ };
10
+
11
+ export default routes(manifest);
@@ -0,0 +1,20 @@
1
+ {
2
+ "dev": {
3
+ "port": 5173,
4
+ "proxy": {}
5
+ },
6
+ "build": {
7
+ "out": "out",
8
+ "dist": "dist",
9
+ "publicDir": "public"
10
+ },
11
+ "bake": {
12
+ "entry": "src/routes.ts",
13
+ "template": "index.html",
14
+ "baseUrl": "https://example.com"
15
+ },
16
+ "bundle": {
17
+ "splitting": true,
18
+ "compress": ["gz", "br"]
19
+ }
20
+ }
@@ -4,10 +4,14 @@
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
7
- "build": "tsc -p tsconfig.json",
8
- "typecheck": "tsc -p tsconfig.json --noEmit",
7
+ "build": "mado build",
8
+ "typecheck": "mado typecheck",
9
+ "dev": "mado dev",
9
10
  "serve": "mado serve",
10
- "dev": "mado dev"
11
+ "bundle": "mado bundle",
12
+ "bake": "mado bake",
13
+ "release": "mado release",
14
+ "preview": "mado preview"
11
15
  },
12
16
  "dependencies": {
13
17
  "@madojs/mado": "__MADOJS_VERSION__"
@@ -1,6 +1,8 @@
1
1
  import { routes } from "@madojs/mado";
2
2
 
3
- export default routes({
3
+ export const manifest = {
4
4
  "/": () => import("./pages/home.js"),
5
5
  "*": () => import("./pages/not-found.js"),
6
- });
6
+ };
7
+
8
+ export default routes(manifest);