cronus-ui 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/commands/add-page.js +17 -2
- package/dist/commands/upgrade.js +7 -2
- package/dist/compose/gold-path.d.ts +21 -3
- package/dist/compose/gold-path.js +113 -5
- package/dist/config.d.ts +2 -2
- package/dist/config.js +1 -1
- package/package.json +2 -2
- package/templates/apps/admin.json +1 -1
- package/templates/apps/saas.json +1 -1
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ Notes that match the commander surface:
|
|
|
49
49
|
`packages/cli/scripts/build-registry.ts` — each item carries its source, its npm
|
|
50
50
|
`dependencies`, and its `registryDependencies` (other components it imports),
|
|
51
51
|
derived by parsing imports.
|
|
52
|
-
- The default registry is pinned to the CLI package version (`v0.7.
|
|
52
|
+
- The default registry is pinned to the CLI package version (`v0.7.2` here), not
|
|
53
53
|
mutable `main`, so a published CLI reads the registry snapshot it was released
|
|
54
54
|
with. Use `-r, --registry ./registry` when testing local registry changes before
|
|
55
55
|
a release tag exists.
|
|
@@ -80,7 +80,7 @@ Notes that match the commander surface:
|
|
|
80
80
|
"lib": "lib",
|
|
81
81
|
"blocks": "components/blocks"
|
|
82
82
|
},
|
|
83
|
-
"registry": "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.7.
|
|
83
|
+
"registry": "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.7.2/registry"
|
|
84
84
|
}
|
|
85
85
|
```
|
|
86
86
|
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
* inherited wholesale from the shared renderer.
|
|
20
20
|
*/
|
|
21
21
|
import { existsSync } from "node:fs";
|
|
22
|
-
import { rm } from "node:fs/promises";
|
|
23
|
-
import { goldPatchAppShellChrome, goldPatchHomePage, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, } from "../compose/gold-path.js";
|
|
22
|
+
import { readFile, rm } from "node:fs/promises";
|
|
23
|
+
import { GOLD_PATH_AUTH_SPLIT_FILES, goldPatchAppShellChrome, goldPatchHomePage, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, patchGoldPathAuthSplit, } from "../compose/gold-path.js";
|
|
24
24
|
import { blockRefParts } from "../compose/manifest.js";
|
|
25
25
|
import { buildComposePlan, ComposePlanError, } from "../compose/plan.js";
|
|
26
26
|
import { baseSnapshotDir, reloadManifest } from "../compose/reload.js";
|
|
@@ -306,6 +306,21 @@ export async function addPage(options) {
|
|
|
306
306
|
generatedFiles.push(rel);
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
|
+
if (isGoldPathTemplate(appName)) {
|
|
310
|
+
for (const file of GOLD_PATH_AUTH_SPLIT_FILES) {
|
|
311
|
+
const rel = `${config.paths.blocks}/${file}`;
|
|
312
|
+
const dest = resolveSafeDest(targetDir, ".", rel);
|
|
313
|
+
if (!existsSync(dest))
|
|
314
|
+
continue;
|
|
315
|
+
const current = await readFile(dest, "utf8");
|
|
316
|
+
const patched = patchGoldPathAuthSplit(current);
|
|
317
|
+
if (patched === undefined || patched === current)
|
|
318
|
+
continue;
|
|
319
|
+
await writeFileEnsured(dest, patched);
|
|
320
|
+
if (!generatedFiles.includes(rel))
|
|
321
|
+
generatedFiles.push(rel);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
309
324
|
// --- Grow composed{} (pages union + files union) + persist ----------------
|
|
310
325
|
const nextPages = [...new Set([...composedRecord.choices.pages, options.route])];
|
|
311
326
|
// Preserve manifest order of the routes the app actually has.
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -5,7 +5,7 @@ import { tmpdir } from "node:os";
|
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { createInterface } from "node:readline/promises";
|
|
7
7
|
import pc from "picocolors";
|
|
8
|
-
import { goldPatchAppShellChrome, goldPatchHomePage, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, reemitGoldPathOwned, } from "../compose/gold-path.js";
|
|
8
|
+
import { GOLD_PATH_AUTH_SPLIT_FILES, goldPatchAppShellChrome, goldPatchHomePage, goldPatchShellLayout, goldPatchTeamPage, goldPathLayout, isGoldPathTemplate, patchGoldPathAccountIssuer, patchGoldPathAuthSplit, reemitGoldPathOwned, } from "../compose/gold-path.js";
|
|
9
9
|
import { buildComposePlan } from "../compose/plan.js";
|
|
10
10
|
import { baseSnapshotDest, filterManifestToComposedPages, listBaseSnapshotRels, readBaseSnapshot, reloadManifest, } from "../compose/reload.js";
|
|
11
11
|
import { renderPlan } from "../compose/render.js";
|
|
@@ -484,7 +484,12 @@ async function repatchGoldPathSurfaces(cwd, config, composed) {
|
|
|
484
484
|
if (!Object.keys(composed).some((key) => isGoldPathTemplate(key)))
|
|
485
485
|
return;
|
|
486
486
|
const authImport = `${config.aliases.lib}/auth`;
|
|
487
|
-
|
|
487
|
+
const layout = goldPathLayout(config);
|
|
488
|
+
await repatchGoldPathFile(cwd, `${layout.dbDir}/schema.ts`, patchGoldPathAccountIssuer, "account.issuer nullable");
|
|
489
|
+
await repatchGoldPathFile(cwd, join(config.paths.blocks, "app-shell-chrome.tsx"), goldPatchAppShellChrome, "WorkspaceMenu / InviteMember / SessionUser / nav / notifications");
|
|
490
|
+
for (const file of GOLD_PATH_AUTH_SPLIT_FILES) {
|
|
491
|
+
await repatchGoldPathFile(cwd, join(config.paths.blocks, file), patchGoldPathAuthSplit, "auth split without Dana Reyes");
|
|
492
|
+
}
|
|
488
493
|
for (const rel of goldPathSurfaceRels(cwd, composed)) {
|
|
489
494
|
if (/(^|\/)\(shell\)\/layout\.tsx$/.test(rel)) {
|
|
490
495
|
await repatchGoldPathFile(cwd, rel, (source) => goldPatchShellLayout(source, authImport), "session gate");
|
|
@@ -6,11 +6,14 @@ import type { CronusUIConfig } from "../config.js";
|
|
|
6
6
|
export declare const GOLD_PATH_TEMPLATES: Set<string>;
|
|
7
7
|
export declare function isGoldPathTemplate(name: string): boolean;
|
|
8
8
|
/**
|
|
9
|
-
* Re-apply WorkspaceMenu / InviteMember / SessionUser onto catalog app-shell-chrome
|
|
10
|
-
*
|
|
11
|
-
* and upgrade so neither restores Mara
|
|
9
|
+
* Re-apply WorkspaceMenu / InviteMember / SessionUser onto catalog app-shell-chrome,
|
|
10
|
+
* drop catalog demo routes from APP_NAV, and remove the dead Notifications button.
|
|
11
|
+
* Idempotent. Used by add-page --nav and upgrade so neither restores Mara,
|
|
12
|
+
* Analytics/Billing/Settings in the nav, nor a no-op Bell.
|
|
12
13
|
*/
|
|
13
14
|
export declare function goldPatchAppShellChrome(source: string): string | undefined;
|
|
15
|
+
/** Installed split-auth copies compose writes for saas/admin. */
|
|
16
|
+
export declare const GOLD_PATH_AUTH_SPLIT_FILES: readonly ["login-split.tsx", "signup-split.tsx", "forgot-password-split.tsx"];
|
|
14
17
|
/**
|
|
15
18
|
* Re-apply the session gate onto a catalog shell layout.
|
|
16
19
|
* Idempotent. Used by add-page (new shell group) and upgrade.
|
|
@@ -49,6 +52,21 @@ export interface ApplyGoldPathResult {
|
|
|
49
52
|
skipped: string[];
|
|
50
53
|
}
|
|
51
54
|
export declare function goldPathLayout(config: CronusUIConfig): GoldPathLayout;
|
|
55
|
+
/**
|
|
56
|
+
* Drop the catalog Dana Reyes / Northwind testimonial column from a split auth
|
|
57
|
+
* block. Idempotent. Returns undefined when the quote is missing and the file
|
|
58
|
+
* is not an already-stripped gold-path split.
|
|
59
|
+
*/
|
|
60
|
+
export declare function patchGoldPathAuthSplit(source: string): string | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Drop `.notNull()` on `account.issuer`. Better Auth 1.7.3 never writes the
|
|
63
|
+
* column and refuses a required one (`SCHEMA_MISMATCH`). Idempotent. Does not
|
|
64
|
+
* rewrite the rest of a user-owned schema — used by compose and `upgrade --all`
|
|
65
|
+
* so 0.7.1 apps pick up the fix without losing hand edits.
|
|
66
|
+
*/
|
|
67
|
+
export declare function patchGoldPathAccountIssuer(source: string): string | undefined;
|
|
68
|
+
/** Remove the no-op Notifications Bell from gold-path chrome. Idempotent. */
|
|
69
|
+
export declare function patchGoldPathChromeNotifications(source: string): string | undefined;
|
|
52
70
|
/**
|
|
53
71
|
* Drop catalog demo hrefs from `const APP_NAV`. Idempotent. Keeps Items, Team,
|
|
54
72
|
* and any user-added link. Returns undefined when the const is missing.
|
|
@@ -20,13 +20,20 @@ const GOLD_AUTH_IMPORT = "@/lib/auth";
|
|
|
20
20
|
const GOLD_MEMBERS_IMPORT = "@/components/members-panel";
|
|
21
21
|
const GOLD_ITEMS_IMPORT = "@/components/items-panel";
|
|
22
22
|
/**
|
|
23
|
-
* Re-apply WorkspaceMenu / InviteMember / SessionUser onto catalog app-shell-chrome
|
|
24
|
-
*
|
|
25
|
-
* and upgrade so neither restores Mara
|
|
23
|
+
* Re-apply WorkspaceMenu / InviteMember / SessionUser onto catalog app-shell-chrome,
|
|
24
|
+
* drop catalog demo routes from APP_NAV, and remove the dead Notifications button.
|
|
25
|
+
* Idempotent. Used by add-page --nav and upgrade so neither restores Mara,
|
|
26
|
+
* Analytics/Billing/Settings in the nav, nor a no-op Bell.
|
|
26
27
|
*/
|
|
27
28
|
export function goldPatchAppShellChrome(source) {
|
|
28
29
|
return patchChromeSource(source, GOLD_WORKSPACE_IMPORT, GOLD_INVITE_IMPORT, GOLD_SESSION_IMPORT);
|
|
29
30
|
}
|
|
31
|
+
/** Installed split-auth copies compose writes for saas/admin. */
|
|
32
|
+
export const GOLD_PATH_AUTH_SPLIT_FILES = [
|
|
33
|
+
"login-split.tsx",
|
|
34
|
+
"signup-split.tsx",
|
|
35
|
+
"forgot-password-split.tsx",
|
|
36
|
+
];
|
|
30
37
|
/**
|
|
31
38
|
* Re-apply the session gate onto a catalog shell layout.
|
|
32
39
|
* Idempotent. Used by add-page (new shell group) and upgrade.
|
|
@@ -180,7 +187,7 @@ export const session = sqliteTable("session", {
|
|
|
180
187
|
|
|
181
188
|
export const account = sqliteTable("account", {
|
|
182
189
|
id: text("id").primaryKey(),
|
|
183
|
-
issuer: text("issuer")
|
|
190
|
+
issuer: text("issuer"),
|
|
184
191
|
accountId: text("account_id").notNull(),
|
|
185
192
|
providerId: text("provider_id").notNull(),
|
|
186
193
|
userId: text("user_id")
|
|
@@ -1125,6 +1132,76 @@ function serializeGoldPathAppNav(links) {
|
|
|
1125
1132
|
.join("\n");
|
|
1126
1133
|
return `const APP_NAV = [\n${rows}\n];`;
|
|
1127
1134
|
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Drop the catalog Dana Reyes / Northwind testimonial column from a split auth
|
|
1137
|
+
* block. Idempotent. Returns undefined when the quote is missing and the file
|
|
1138
|
+
* is not an already-stripped gold-path split.
|
|
1139
|
+
*/
|
|
1140
|
+
export function patchGoldPathAuthSplit(source) {
|
|
1141
|
+
const hasQuote = source.includes("Dana Reyes") || source.includes("Northwind Labs");
|
|
1142
|
+
if (!hasQuote) {
|
|
1143
|
+
if (source.includes("lg:grid-cols-2"))
|
|
1144
|
+
return undefined;
|
|
1145
|
+
if (source.includes("Sign in to your Cronus workspace") ||
|
|
1146
|
+
source.includes("Create your Cronus workspace") ||
|
|
1147
|
+
source.includes("Join the workspace") ||
|
|
1148
|
+
source.includes("Check your inbox")) {
|
|
1149
|
+
return source;
|
|
1150
|
+
}
|
|
1151
|
+
return undefined;
|
|
1152
|
+
}
|
|
1153
|
+
let out = source.replace(/(?:\n\s*\{\/\* Brand panel \*\/\})?\s*<div className="relative overflow-hidden bg-gradient-primary-strong[\s\S]*?Head of Growth, Northwind Labs[\s\S]*?<\/figure>\s*<\/div>\s*<\/div>/, "");
|
|
1154
|
+
if (out === source)
|
|
1155
|
+
return undefined;
|
|
1156
|
+
out = out.replace(" lg:grid-cols-2", "");
|
|
1157
|
+
out = out.replace(" max-w-4xl", " max-w-md");
|
|
1158
|
+
out = out.replace(" lg:order-2", "");
|
|
1159
|
+
out = out.replace(" lg:order-1", "");
|
|
1160
|
+
out = dropUnusedFromImport(out, "lucide-react");
|
|
1161
|
+
out = dropUnusedFromImport(out, "@cronus-ui/ui");
|
|
1162
|
+
return out;
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Drop `.notNull()` on `account.issuer`. Better Auth 1.7.3 never writes the
|
|
1166
|
+
* column and refuses a required one (`SCHEMA_MISMATCH`). Idempotent. Does not
|
|
1167
|
+
* rewrite the rest of a user-owned schema — used by compose and `upgrade --all`
|
|
1168
|
+
* so 0.7.1 apps pick up the fix without losing hand edits.
|
|
1169
|
+
*/
|
|
1170
|
+
export function patchGoldPathAccountIssuer(source) {
|
|
1171
|
+
const next = source.replace(/(issuer:\s*(?:text|varchar)\([^)]*\))\s*\.notNull\(\)/g, "$1");
|
|
1172
|
+
if (next === source)
|
|
1173
|
+
return undefined;
|
|
1174
|
+
return next;
|
|
1175
|
+
}
|
|
1176
|
+
/** Remove the no-op Notifications Bell from gold-path chrome. Idempotent. */
|
|
1177
|
+
export function patchGoldPathChromeNotifications(source) {
|
|
1178
|
+
if (!source.includes('aria-label="Notifications"'))
|
|
1179
|
+
return undefined;
|
|
1180
|
+
let out = source.replace(/\n\s*<Button variant="ghost" size="icon-sm" aria-label="Notifications">\s*<Bell className="size-4" aria-hidden="true" \/>\s*<\/Button>/, "");
|
|
1181
|
+
if (out === source)
|
|
1182
|
+
return undefined;
|
|
1183
|
+
out = dropUnusedFromImport(out, "lucide-react");
|
|
1184
|
+
return out;
|
|
1185
|
+
}
|
|
1186
|
+
function dropUnusedFromImport(source, fromModule) {
|
|
1187
|
+
const escaped = fromModule.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1188
|
+
const re = new RegExp(`import \\{([^}]+)\\} from "${escaped}";\\n`);
|
|
1189
|
+
const match = source.match(re);
|
|
1190
|
+
if (!match || match.index === undefined)
|
|
1191
|
+
return source;
|
|
1192
|
+
const names = (match[1] ?? "")
|
|
1193
|
+
.split(",")
|
|
1194
|
+
.map((part) => part.trim())
|
|
1195
|
+
.filter(Boolean);
|
|
1196
|
+
const rest = source.slice(0, match.index) + source.slice(match.index + match[0].length);
|
|
1197
|
+
const kept = names.filter((name) => new RegExp(`(?:<|{)${name}\\b`).test(rest));
|
|
1198
|
+
if (kept.length === names.length)
|
|
1199
|
+
return source;
|
|
1200
|
+
if (kept.length === 0) {
|
|
1201
|
+
return source.slice(0, match.index) + source.slice(match.index + match[0].length);
|
|
1202
|
+
}
|
|
1203
|
+
return `${source.slice(0, match.index)}import { ${kept.join(", ")} } from "${fromModule}";\n${source.slice(match.index + match[0].length)}`;
|
|
1204
|
+
}
|
|
1128
1205
|
/**
|
|
1129
1206
|
* Drop catalog demo hrefs from `const APP_NAV`. Idempotent. Keeps Items, Team,
|
|
1130
1207
|
* and any user-added link. Returns undefined when the const is missing.
|
|
@@ -1207,9 +1284,12 @@ export function patchChromeSource(source, workspaceImport, inviteImport, session
|
|
|
1207
1284
|
const navPatched = patchGoldPathAppNav(out);
|
|
1208
1285
|
if (navPatched !== undefined)
|
|
1209
1286
|
out = navPatched;
|
|
1287
|
+
const notifyPatched = patchGoldPathChromeNotifications(out);
|
|
1288
|
+
if (notifyPatched !== undefined)
|
|
1289
|
+
out = notifyPatched;
|
|
1210
1290
|
if (out !== source)
|
|
1211
1291
|
return out;
|
|
1212
|
-
if (widgetsTouched || navPatched !== undefined)
|
|
1292
|
+
if (widgetsTouched || (navPatched !== undefined && navPatched === source))
|
|
1213
1293
|
return source;
|
|
1214
1294
|
return undefined;
|
|
1215
1295
|
}
|
|
@@ -1485,6 +1565,20 @@ export async function applyGoldPath(options) {
|
|
|
1485
1565
|
for (const file of files) {
|
|
1486
1566
|
await writeRel(targetDir, file.rel, file.content, overwrite, file.always === true, written, skipped);
|
|
1487
1567
|
}
|
|
1568
|
+
const schemaRel = `${layout.dbDir}/schema.ts`;
|
|
1569
|
+
const schemaDest = resolveSafeDest(targetDir, ".", schemaRel);
|
|
1570
|
+
if (existsSync(schemaDest)) {
|
|
1571
|
+
const current = await readFile(schemaDest, "utf8");
|
|
1572
|
+
const patched = patchGoldPathAccountIssuer(current);
|
|
1573
|
+
if (patched !== undefined && patched !== current) {
|
|
1574
|
+
await writeFileEnsured(schemaDest, patched);
|
|
1575
|
+
if (!written.includes(schemaRel))
|
|
1576
|
+
written.push(schemaRel);
|
|
1577
|
+
const skipAt = skipped.indexOf(schemaRel);
|
|
1578
|
+
if (skipAt >= 0)
|
|
1579
|
+
skipped.splice(skipAt, 1);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1488
1582
|
const chromeDest = resolveSafeDest(targetDir, ".", chromeRel);
|
|
1489
1583
|
if (existsSync(chromeDest)) {
|
|
1490
1584
|
const current = await readFile(chromeDest, "utf8");
|
|
@@ -1500,6 +1594,20 @@ export async function applyGoldPath(options) {
|
|
|
1500
1594
|
}
|
|
1501
1595
|
}
|
|
1502
1596
|
}
|
|
1597
|
+
const blocksDir = posix(config.paths.blocks);
|
|
1598
|
+
for (const file of GOLD_PATH_AUTH_SPLIT_FILES) {
|
|
1599
|
+
const rel = `${blocksDir}/${file}`;
|
|
1600
|
+
const dest = resolveSafeDest(targetDir, ".", rel);
|
|
1601
|
+
if (!existsSync(dest))
|
|
1602
|
+
continue;
|
|
1603
|
+
const current = await readFile(dest, "utf8");
|
|
1604
|
+
const patched = patchGoldPathAuthSplit(current);
|
|
1605
|
+
if (patched === undefined || patched === current)
|
|
1606
|
+
continue;
|
|
1607
|
+
await writeFileEnsured(dest, patched);
|
|
1608
|
+
if (!written.includes(rel))
|
|
1609
|
+
written.push(rel);
|
|
1610
|
+
}
|
|
1503
1611
|
const layoutRel = shellLayoutRel(appDir, generatedFiles);
|
|
1504
1612
|
if (layoutRel !== undefined) {
|
|
1505
1613
|
const dest = resolveSafeDest(targetDir, ".", layoutRel);
|
package/dist/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const CONFIG_FILE = "cronus-ui.json";
|
|
2
|
-
export declare const CLI_VERSION = "0.7.
|
|
3
|
-
export declare const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.7.
|
|
2
|
+
export declare const CLI_VERSION = "0.7.2";
|
|
3
|
+
export declare const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.7.2/registry";
|
|
4
4
|
/** Manifest entry `add`/`upgrade` record per installed registry item. */
|
|
5
5
|
export interface InstalledRecord {
|
|
6
6
|
/** Registry release the files came from (git tag without the leading "v"). */
|
package/dist/config.js
CHANGED
|
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
export const CONFIG_FILE = "cronus-ui.json";
|
|
5
|
-
export const CLI_VERSION = "0.7.
|
|
5
|
+
export const CLI_VERSION = "0.7.2";
|
|
6
6
|
export const DEFAULT_REGISTRY = `https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v${CLI_VERSION}/registry`;
|
|
7
7
|
export const DEFAULT_CONFIG = {
|
|
8
8
|
aliases: { ui: "@/components/ui", lib: "@/lib", blocks: "@/components/blocks" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cronus-ui",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "cronus-ui — add Cronus UI components to your project, shadcn-style (copy-paste registry).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"registry:check": "bun run scripts/check-registry.ts"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@cronus-ui/ai-kit": "0.7.
|
|
57
|
+
"@cronus-ui/ai-kit": "0.7.2",
|
|
58
58
|
"commander": "^15.0.0",
|
|
59
59
|
"picocolors": "^1.1.1"
|
|
60
60
|
},
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"planVersion": 1,
|
|
5
5
|
"manifest": {
|
|
6
6
|
"title": "Admin",
|
|
7
|
-
"description": "
|
|
7
|
+
"description": "Authenticated gold path: split login/signup, password reset, Items in a sidebar shell. Catalog demo pages (users, analytics, board, audit) ship as files, not in the nav — composed from validated blocks.",
|
|
8
8
|
"chrome": {
|
|
9
9
|
"shell": { "block": "app-shell-chrome" },
|
|
10
10
|
"bare": {}
|
package/templates/apps/saas.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"planVersion": 1,
|
|
5
5
|
"manifest": {
|
|
6
6
|
"title": "SaaS",
|
|
7
|
-
"description": "
|
|
7
|
+
"description": "Authenticated gold path: split login/signup, password reset, Items and Team in a sidebar shell. Catalog demo pages (analytics, billing, settings, welcome, setup wizard, checklist) ship as files, not in the nav — all from validated blocks.",
|
|
8
8
|
"chrome": {
|
|
9
9
|
"shell": { "block": "app-shell-chrome" },
|
|
10
10
|
"bare": {}
|