create-bw-app 0.12.0 → 0.13.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.
- package/README.md +6 -6
- package/package.json +1 -1
- package/src/add.mjs +2 -1
- package/src/app-manifest.mjs +1 -0
- package/src/constants.mjs +4 -9
- package/src/generator.mjs +64 -56
- package/src/remove.mjs +2 -0
- package/src/update.mjs +3 -0
- package/template/base/AGENTS.md +16 -20
- package/template/base/app/globals.css +5 -569
- package/template/base/app/theme.css +5 -0
- package/template/base/config/modules.ts +3 -5
- package/template/base/docs/ai/README.md +15 -41
- package/template/base/docs/ai/examples.md +13 -34
- package/template/base/public/brand/logo-dark.svg +2 -2
- package/template/base/public/brand/logo-light.svg +2 -2
- package/template/modules/admin/app/admin/users/page.tsx +2 -0
- package/template/modules/admin/app/api/admin/users/roles/route.ts +1 -6
- package/template/modules/admin/app/api/admin/users/route.ts +1 -6
- package/template/modules/crm/app/api/crm/contacts/route.ts +3 -18
- package/template/modules/crm/app/api/crm/organizations/route.ts +1 -8
- package/template/modules/crm/app/api/crm/owners/route.ts +1 -8
- package/template/modules/crm/app/api/crm/stats/route.ts +1 -8
- package/template/modules/crm/app/api/crm/timeline/route.ts +1 -8
- package/template/site/base/AGENTS.md +6 -19
- package/template/site/base/docs/ai/README.md +6 -33
- package/template/site/base/docs/ai/examples.md +6 -28
- package/template/base/app/bootstrap/page.tsx +0 -75
- package/template/base/app/page.tsx +0 -145
- package/template/base/app/playground/auth/page.tsx +0 -5
- package/template/base/app/playground/layout.tsx +0 -41
- package/template/base/app/preview/app-shell/page.tsx +0 -11
- package/template/base/components/app-shell-preview.tsx +0 -185
- package/template/base/components/auth-playground.tsx +0 -112
- package/template/base/config/bootstrap.ts +0 -131
- package/template/base/config/client.ts +0 -18
- package/template/base/config/env.ts +0 -100
- package/template/base/lib/email/resend-base.ts +0 -13
- package/template/modules/admin/app/playground/admin/page.tsx +0 -102
- package/template/modules/crm/app/api/crm/_shared/create-module-route-handler.ts +0 -13
- package/template/modules/projects/app/playground/projects/page.tsx +0 -93
- package/template/site/base/app/page.tsx +0 -165
- package/template/site/base/components/ui/badge.tsx +0 -28
- package/template/site/base/components/ui/button.tsx +0 -52
- package/template/site/base/components/ui/card.tsx +0 -28
- package/template/site/base/components.json +0 -17
- package/template/site/base/lib/utils.ts +0 -6
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ bw upgrade
|
|
|
35
35
|
bw doctor
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
- `bw add <moduleKey>` resolves requirements, installs
|
|
38
|
+
- `bw add <moduleKey>` resolves requirements, installs thin package mounts and module wiring, and appends migrations.
|
|
39
39
|
- `bw upgrade [moduleKey]` includes the existing managed update flow plus forward-only module migrations.
|
|
40
40
|
- `bw doctor` checks package, config, scaffold, environment-name, and migration consistency. Add `--report` to stamp the result in the app manifest.
|
|
41
41
|
- All mutating commands support `--dry-run`.
|
|
@@ -58,7 +58,7 @@ Current updater behavior:
|
|
|
58
58
|
- fails the update if npm resolution fails unless you pass `--allow-stale-fallback`
|
|
59
59
|
- re-syncs managed BrightWeb config files such as `next.config.ts`, `config/modules.ts`, and `config/shell.ts`
|
|
60
60
|
- preserves app-owned shell customizations in the scaffolded `config/shell.overrides.ts`
|
|
61
|
-
- reports missing or drifted
|
|
61
|
+
- reports missing or drifted scaffold mounts and only rewrites them with `--refresh-starters`
|
|
62
62
|
- prints the follow-up install command unless `--install` is passed
|
|
63
63
|
- preserves unrelated third-party dependencies and app-owned product pages
|
|
64
64
|
|
|
@@ -69,10 +69,10 @@ Current updater behavior:
|
|
|
69
69
|
- prompts for optional platform modules: `admin`, `crm`, and `projects`
|
|
70
70
|
- prompts to install dependencies immediately
|
|
71
71
|
- copies a clean Next.js App Router starter template
|
|
72
|
-
- platform apps include BrightWeb auth, shell wiring, and optional
|
|
73
|
-
-
|
|
72
|
+
- platform apps include BrightWeb auth, shell wiring, and optional direct package mounts
|
|
73
|
+
- generated route files contain direct `@brightweblabs/*` re-exports only
|
|
74
74
|
- platform apps in published mode also write `supabase/config.toml`, a CLI-ready flat `supabase/migrations/` folder, `supabase/module-registry.json`, `supabase/clients/<slug>/stack.json`, and the resolved shared SQL migrations under `supabase/modules/<module>/migrations`
|
|
75
|
-
- site apps include Next.js
|
|
75
|
+
- site apps include a thin Next.js and Tailwind CSS shell with no default feature page or local component library
|
|
76
76
|
- writes `package.json`, `next.config.ts`, `.gitignore`, and `README.md` for both templates
|
|
77
77
|
- platform apps also write `.env.local`, `AGENTS.md`, `docs/ai/README.md`, `docs/ai/examples.md`, `docs/ai/app-context.json`, and generated config files for brand and module state
|
|
78
78
|
- site apps also write `AGENTS.md`, `docs/ai/README.md`, `docs/ai/examples.md`, and `docs/ai/app-context.json` for app-local AI handoff
|
|
@@ -88,7 +88,7 @@ When this package runs in BrightWeb workspace mode, it can:
|
|
|
88
88
|
- create `supabase/clients/<slug>/stack.json`
|
|
89
89
|
- create a client-only migrations folder so database planning stays aligned with scaffolded modules
|
|
90
90
|
|
|
91
|
-
Platform mode always resolves to the `Core + Admin` database baseline. Selecting `admin` affects the Admin
|
|
91
|
+
Platform mode always resolves to the `Core + Admin` database baseline. Selecting `admin` affects the Admin package mount and wiring, not whether the Admin database layer exists.
|
|
92
92
|
|
|
93
93
|
## Related references
|
|
94
94
|
|
package/package.json
CHANGED
package/src/add.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { stdout as output } from "node:process";
|
|
4
4
|
import { SELECTABLE_MODULES } from "./constants.mjs";
|
|
5
|
-
import { TEMPLATE_ROOT, createAppContextFile, createDbInstallPlan, createNextConfig, createPlatformModulesConfigFile, createShellConfig, getDbModuleRegistry, getVersionMap, pathExists, readJsonIfPresent } from "./generator.mjs";
|
|
5
|
+
import { TEMPLATE_ROOT, createAppContextFile, createDbInstallPlan, createNextConfig, createPlatformGlobalsCss, createPlatformModulesConfigFile, createShellConfig, getDbModuleRegistry, getVersionMap, pathExists, readJsonIfPresent } from "./generator.mjs";
|
|
6
6
|
import { collectScaffoldFiles, findWorkspaceRoot, loadModuleCatalog, MODULE_PACKAGES, readAppManifest, resolveModuleClosure, satisfiesVersion, writeAppManifest } from "./app-manifest.mjs";
|
|
7
7
|
import { applyMigrationWrites, planMigrationAppends } from "./migrations.mjs";
|
|
8
8
|
|
|
@@ -65,6 +65,7 @@ export async function addBrightwebModule(moduleKey, argvOptions = {}, runtimeOpt
|
|
|
65
65
|
}
|
|
66
66
|
const managedWrites = {
|
|
67
67
|
"next.config.ts": createNextConfig({ template: "platform", selectedModules: installedModuleKeys }),
|
|
68
|
+
"app/globals.css": await createPlatformGlobalsCss(installedModuleKeys),
|
|
68
69
|
"config/modules.ts": createPlatformModulesConfigFile(installedModuleKeys),
|
|
69
70
|
"config/shell.ts": createShellConfig(installedModuleKeys),
|
|
70
71
|
"docs/ai/app-context.json": createAppContextFile({ slug: appManifest.app.slug, template: "platform", selectedModules: installedModuleKeys.filter((key) => key !== "orgs"), dbInstallPlan }),
|
package/src/app-manifest.mjs
CHANGED
|
@@ -18,6 +18,7 @@ async function readJsonIfPresent(filePath) {
|
|
|
18
18
|
export const APP_MANIFEST_PATH = path.join(".brightweb", "app-manifest.json");
|
|
19
19
|
export const MANAGED_APP_FILES = [
|
|
20
20
|
"next.config.ts",
|
|
21
|
+
"app/globals.css",
|
|
21
22
|
"config/modules.ts",
|
|
22
23
|
"config/shell.ts",
|
|
23
24
|
"docs/ai/app-context.json",
|
package/src/constants.mjs
CHANGED
|
@@ -10,7 +10,7 @@ export const TEMPLATE_OPTIONS = [
|
|
|
10
10
|
{
|
|
11
11
|
key: "site",
|
|
12
12
|
label: "Site",
|
|
13
|
-
description: "
|
|
13
|
+
description: "Thin Next.js + Tailwind site shell for package-owned surfaces.",
|
|
14
14
|
},
|
|
15
15
|
];
|
|
16
16
|
|
|
@@ -55,7 +55,7 @@ export const MODULE_STARTER_FILES = {
|
|
|
55
55
|
admin: [
|
|
56
56
|
"app/api/admin/users/route.ts",
|
|
57
57
|
"app/api/admin/users/roles/route.ts",
|
|
58
|
-
"app/
|
|
58
|
+
"app/admin/users/page.tsx",
|
|
59
59
|
],
|
|
60
60
|
crm: [
|
|
61
61
|
"app/crm/layout.tsx",
|
|
@@ -67,7 +67,6 @@ export const MODULE_STARTER_FILES = {
|
|
|
67
67
|
"app/api/crm/timeline/route.ts",
|
|
68
68
|
],
|
|
69
69
|
projects: [
|
|
70
|
-
"app/playground/projects/page.tsx",
|
|
71
70
|
],
|
|
72
71
|
};
|
|
73
72
|
|
|
@@ -79,7 +78,7 @@ export const APP_DEPENDENCY_DEFAULTS = {
|
|
|
79
78
|
"@brightweblabs/app-shell": "^0.4.1",
|
|
80
79
|
"@brightweblabs/core-auth": "^0.3.4",
|
|
81
80
|
"@brightweblabs/infra": "^0.3.1",
|
|
82
|
-
"@brightweblabs/module-admin": "^0.
|
|
81
|
+
"@brightweblabs/module-admin": "^0.4.0",
|
|
83
82
|
"@brightweblabs/module-crm": "^0.5.2",
|
|
84
83
|
"@brightweblabs/module-orgs": "^0.2.2",
|
|
85
84
|
"@brightweblabs/module-projects": "^0.4.3",
|
|
@@ -92,13 +91,9 @@ export const APP_DEPENDENCY_DEFAULTS = {
|
|
|
92
91
|
};
|
|
93
92
|
|
|
94
93
|
export const SITE_DEPENDENCY_DEFAULTS = {
|
|
95
|
-
"class-variance-authority": "^0.7.1",
|
|
96
|
-
"clsx": "^2.1.1",
|
|
97
|
-
"lucide-react": "^1.8.0",
|
|
98
94
|
"next": "16.1.6",
|
|
99
95
|
"react": "19.2.3",
|
|
100
96
|
"react-dom": "19.2.3",
|
|
101
|
-
"tailwind-merge": "^3.4.0",
|
|
102
97
|
};
|
|
103
98
|
|
|
104
99
|
export const APP_DEV_DEPENDENCY_DEFAULTS = {
|
|
@@ -149,6 +144,6 @@ Update options:
|
|
|
149
144
|
--package-manager <name> Override package manager: pnpm, npm, yarn, or bun
|
|
150
145
|
--allow-stale-fallback Use baked-in BrightWeb package versions if npm lookup fails
|
|
151
146
|
--install Run install after writing package changes
|
|
152
|
-
--refresh-starters Rewrite
|
|
147
|
+
--refresh-starters Rewrite tracked package mount files from the latest template
|
|
153
148
|
--dry-run Print the update plan without writing files
|
|
154
149
|
`.trim();
|
package/src/generator.mjs
CHANGED
|
@@ -198,7 +198,7 @@ export function createDbInstallPlan({ selectedModules, workspaceMode, registry }
|
|
|
198
198
|
const notes = [];
|
|
199
199
|
|
|
200
200
|
if (!selectedModules.includes("admin") && resolvedOrder.includes("admin")) {
|
|
201
|
-
notes.push("Platform always resolves to the Core + Admin database baseline; selecting Admin only controls whether the Admin
|
|
201
|
+
notes.push("Platform always resolves to the Core + Admin database baseline; selecting Admin only controls whether the Admin package mount and wiring are scaffolded.");
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
for (const moduleKey of resolvedOrder) {
|
|
@@ -315,7 +315,7 @@ export function createPlatformModulesConfigFile(selectedModules) {
|
|
|
315
315
|
" description: string;",
|
|
316
316
|
" enabled: boolean;",
|
|
317
317
|
" packageName: string;",
|
|
318
|
-
"
|
|
318
|
+
" routeHref?: string;",
|
|
319
319
|
' placement: "core" | "primary" | "admin" | "hidden";',
|
|
320
320
|
"};",
|
|
321
321
|
"",
|
|
@@ -326,7 +326,6 @@ export function createPlatformModulesConfigFile(selectedModules) {
|
|
|
326
326
|
' description: "Login, reset-password, callback URLs, and shared auth validation utilities.",',
|
|
327
327
|
" enabled: true,",
|
|
328
328
|
' packageName: "@brightweblabs/core-auth",',
|
|
329
|
-
' playgroundHref: "/playground/auth",',
|
|
330
329
|
' placement: "core",',
|
|
331
330
|
" },",
|
|
332
331
|
" {",
|
|
@@ -343,7 +342,7 @@ export function createPlatformModulesConfigFile(selectedModules) {
|
|
|
343
342
|
' description: "Contacts and CRM server/data layer, with marketing-adjacent operational data stored in Supabase.",',
|
|
344
343
|
` enabled: ${String(selected.has("crm"))},`,
|
|
345
344
|
' packageName: "@brightweblabs/module-crm",',
|
|
346
|
-
'
|
|
345
|
+
' routeHref: "/crm",',
|
|
347
346
|
' placement: "primary",',
|
|
348
347
|
" },",
|
|
349
348
|
" {",
|
|
@@ -352,7 +351,6 @@ export function createPlatformModulesConfigFile(selectedModules) {
|
|
|
352
351
|
' description: "Project portfolio, detail routes, and work-management server logic.",',
|
|
353
352
|
` enabled: ${String(selected.has("projects"))},`,
|
|
354
353
|
' packageName: "@brightweblabs/module-projects",',
|
|
355
|
-
' playgroundHref: "/playground/projects",',
|
|
356
354
|
' placement: "primary",',
|
|
357
355
|
" },",
|
|
358
356
|
" {",
|
|
@@ -361,7 +359,7 @@ export function createPlatformModulesConfigFile(selectedModules) {
|
|
|
361
359
|
' description: "User role governance, admin tools, and access-control surfaces.",',
|
|
362
360
|
` enabled: ${String(selected.has("admin"))},`,
|
|
363
361
|
' packageName: "@brightweblabs/module-admin",',
|
|
364
|
-
'
|
|
362
|
+
' routeHref: "/admin/users",',
|
|
365
363
|
' placement: "admin",',
|
|
366
364
|
" },",
|
|
367
365
|
"];",
|
|
@@ -438,17 +436,15 @@ function createGitignore() {
|
|
|
438
436
|
}
|
|
439
437
|
|
|
440
438
|
function getPlatformStarterRoutes(selectedModules) {
|
|
441
|
-
return
|
|
442
|
-
"/"
|
|
443
|
-
"/
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
...selectedModules.map((moduleKey) => moduleKey === "crm" ? "/crm" : `/playground/${moduleKey}`),
|
|
447
|
-
];
|
|
439
|
+
return selectedModules.flatMap((moduleKey) => {
|
|
440
|
+
if (moduleKey === "crm") return ["/crm"];
|
|
441
|
+
if (moduleKey === "admin") return ["/admin/users"];
|
|
442
|
+
return [];
|
|
443
|
+
});
|
|
448
444
|
}
|
|
449
445
|
|
|
450
446
|
function getSiteStarterRoutes() {
|
|
451
|
-
return [
|
|
447
|
+
return [];
|
|
452
448
|
}
|
|
453
449
|
|
|
454
450
|
function createPlatformReadme({
|
|
@@ -508,7 +504,7 @@ function createPlatformReadme({
|
|
|
508
504
|
"",
|
|
509
505
|
]
|
|
510
506
|
: []),
|
|
511
|
-
"##
|
|
507
|
+
"## Package mounts",
|
|
512
508
|
"",
|
|
513
509
|
...getPlatformStarterRoutes(selectedModules).map((route) => `- \`${route}\``),
|
|
514
510
|
"",
|
|
@@ -542,17 +538,17 @@ function createSiteReadme({ slug, workspaceMode, packageManager }) {
|
|
|
542
538
|
"",
|
|
543
539
|
"- Next.js App Router",
|
|
544
540
|
"- Tailwind CSS v4",
|
|
545
|
-
"-
|
|
541
|
+
"- App-owned settings and theme tokens",
|
|
546
542
|
"",
|
|
547
543
|
"## Local setup",
|
|
548
544
|
"",
|
|
549
545
|
...localSteps,
|
|
550
546
|
"",
|
|
551
|
-
"##
|
|
547
|
+
"## Package mounts",
|
|
552
548
|
"",
|
|
553
549
|
...getSiteStarterRoutes().map((route) => `- \`${route}\``),
|
|
554
550
|
"",
|
|
555
|
-
"
|
|
551
|
+
"This thin scaffold intentionally ships no feature page. Add routes only as thin mounts of package-owned surfaces.",
|
|
556
552
|
"",
|
|
557
553
|
"## AI handoff",
|
|
558
554
|
"",
|
|
@@ -591,33 +587,32 @@ export function createAppContextFile({
|
|
|
591
587
|
"docs/ai/README.md",
|
|
592
588
|
"README.md",
|
|
593
589
|
"config/site.ts",
|
|
594
|
-
"app/page.tsx",
|
|
595
590
|
"app/globals.css",
|
|
596
591
|
],
|
|
597
592
|
appRoutesRoot: "app",
|
|
598
593
|
configRoot: "config",
|
|
599
|
-
componentsRoot: "components",
|
|
600
|
-
uiComponentsRoot: "components/ui",
|
|
601
|
-
libRoot: "lib",
|
|
602
594
|
},
|
|
603
595
|
starterRoutes: getSiteStarterRoutes(),
|
|
604
596
|
ownership: {
|
|
605
597
|
appOwned: [
|
|
606
|
-
"app/**",
|
|
607
|
-
"components/**",
|
|
608
598
|
"config/**",
|
|
609
599
|
"docs/ai/**",
|
|
610
|
-
"lib/**",
|
|
611
600
|
"public/**",
|
|
612
601
|
"AGENTS.md",
|
|
613
602
|
"README.md",
|
|
614
603
|
],
|
|
604
|
+
scaffoldManaged: [
|
|
605
|
+
"app/layout.tsx",
|
|
606
|
+
"app/globals.css",
|
|
607
|
+
"next.config.ts",
|
|
608
|
+
"postcss.config.mjs",
|
|
609
|
+
"tsconfig.json",
|
|
610
|
+
],
|
|
615
611
|
packageOwned: [],
|
|
616
612
|
},
|
|
617
613
|
agentRules: {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
treatStarterHomeAsAppOwned: true,
|
|
614
|
+
keepRoutesAsThinPackageMounts: true,
|
|
615
|
+
doNotAddFeatureOrLibraryCodeToTheApp: true,
|
|
621
616
|
},
|
|
622
617
|
},
|
|
623
618
|
null,
|
|
@@ -649,30 +644,35 @@ export function createAppContextFile({
|
|
|
649
644
|
"docs/ai/README.md",
|
|
650
645
|
"README.md",
|
|
651
646
|
"app/globals.css",
|
|
647
|
+
"app/theme.css",
|
|
652
648
|
"config/brand.ts",
|
|
653
649
|
"config/modules.ts",
|
|
654
|
-
"config/client.ts",
|
|
655
|
-
"config/bootstrap.ts",
|
|
656
650
|
"config/shell.ts",
|
|
657
651
|
"config/shell.overrides.ts",
|
|
658
652
|
".env.local",
|
|
659
653
|
],
|
|
660
654
|
appRoutesRoot: "app",
|
|
661
|
-
componentsRoot: "components",
|
|
662
655
|
configRoot: "config",
|
|
663
656
|
brandAssetsRoot: "public/brand",
|
|
664
657
|
},
|
|
665
658
|
starterRoutes: getPlatformStarterRoutes(selectedModules),
|
|
666
659
|
ownership: {
|
|
667
660
|
appOwned: [
|
|
668
|
-
"app/**",
|
|
669
|
-
"components/**",
|
|
670
661
|
"config/**",
|
|
671
662
|
"docs/ai/**",
|
|
672
663
|
"public/brand/**",
|
|
673
664
|
"AGENTS.md",
|
|
674
665
|
"README.md",
|
|
675
666
|
],
|
|
667
|
+
scaffoldManaged: [
|
|
668
|
+
"app/layout.tsx",
|
|
669
|
+
"app/globals.css",
|
|
670
|
+
"app/**/page.tsx",
|
|
671
|
+
"app/**/route.ts",
|
|
672
|
+
"next.config.ts",
|
|
673
|
+
"postcss.config.mjs",
|
|
674
|
+
"tsconfig.json",
|
|
675
|
+
],
|
|
676
676
|
packageOwned: [
|
|
677
677
|
...CORE_PACKAGES,
|
|
678
678
|
...(selectedModules.includes("crm") || selectedModules.includes("projects") ? [ORGS_PACKAGE_NAME] : []),
|
|
@@ -683,8 +683,8 @@ export function createAppContextFile({
|
|
|
683
683
|
},
|
|
684
684
|
agentRules: {
|
|
685
685
|
checkModulesBeforeEditing: true,
|
|
686
|
-
|
|
687
|
-
|
|
686
|
+
keepRoutesAsThinPackageMounts: true,
|
|
687
|
+
moveFeatureAndLibraryCodeToPackages: true,
|
|
688
688
|
},
|
|
689
689
|
},
|
|
690
690
|
null,
|
|
@@ -711,13 +711,9 @@ export function createPackageJson({
|
|
|
711
711
|
lint: "tsc --noEmit",
|
|
712
712
|
},
|
|
713
713
|
dependencies: sortObjectKeys({
|
|
714
|
-
"class-variance-authority": versionMap["class-variance-authority"],
|
|
715
|
-
"clsx": versionMap.clsx,
|
|
716
|
-
"lucide-react": versionMap["lucide-react"],
|
|
717
714
|
"next": versionMap.next,
|
|
718
715
|
"react": versionMap.react,
|
|
719
716
|
"react-dom": versionMap["react-dom"],
|
|
720
|
-
"tailwind-merge": versionMap["tailwind-merge"],
|
|
721
717
|
}),
|
|
722
718
|
devDependencies: sortObjectKeys({
|
|
723
719
|
"@tailwindcss/postcss": versionMap["@tailwindcss/postcss"],
|
|
@@ -813,6 +809,27 @@ export function createNextConfig({ template, selectedModules }) {
|
|
|
813
809
|
].join("\n");
|
|
814
810
|
}
|
|
815
811
|
|
|
812
|
+
export async function createPlatformGlobalsCss(selectedModules) {
|
|
813
|
+
const template = await fs.readFile(path.join(TEMPLATE_ROOT, "base", "app", "globals.css"), "utf8");
|
|
814
|
+
const sourcePackages = [
|
|
815
|
+
"@brightweblabs/ui",
|
|
816
|
+
"@brightweblabs/app-shell",
|
|
817
|
+
...SELECTABLE_MODULES
|
|
818
|
+
.filter((moduleDefinition) => selectedModules.includes(moduleDefinition.key))
|
|
819
|
+
.map((moduleDefinition) => moduleDefinition.packageName),
|
|
820
|
+
];
|
|
821
|
+
const sourceBlock = [
|
|
822
|
+
"/* BRIGHTWEB_SOURCES_START */",
|
|
823
|
+
...sourcePackages.map((packageName) => `@source "../node_modules/${packageName}/src";`),
|
|
824
|
+
"/* BRIGHTWEB_SOURCES_END */",
|
|
825
|
+
].join("\n");
|
|
826
|
+
|
|
827
|
+
return template.replace(
|
|
828
|
+
/\/\* BRIGHTWEB_SOURCES_START \*\/[\s\S]*?\/\* BRIGHTWEB_SOURCES_END \*\//,
|
|
829
|
+
sourceBlock,
|
|
830
|
+
);
|
|
831
|
+
}
|
|
832
|
+
|
|
816
833
|
export function createShellConfig(selectedModules) {
|
|
817
834
|
const importLines = [];
|
|
818
835
|
const registrationLines = [];
|
|
@@ -832,14 +849,9 @@ export function createShellConfig(selectedModules) {
|
|
|
832
849
|
registrationLines.push(' if (enabled.has("crm")) registrations.push(crmModuleRegistration);');
|
|
833
850
|
}
|
|
834
851
|
|
|
835
|
-
if (selectedModules.includes("projects")) {
|
|
836
|
-
importLines.push('import { projectsModuleRegistration } from "@brightweblabs/module-projects/registration";');
|
|
837
|
-
registrationLines.push(' if (enabled.has("projects")) registrations.push(projectsModuleRegistration);');
|
|
838
|
-
}
|
|
839
|
-
|
|
840
852
|
return [
|
|
841
853
|
"// MANAGED BY BRIGHTWEB — regenerated by create-bw-app update; put customizations in config/shell.overrides.ts",
|
|
842
|
-
'import {
|
|
854
|
+
'import { Wrench } from "lucide-react";',
|
|
843
855
|
"import {",
|
|
844
856
|
" applyShellRegistrationOverrides,",
|
|
845
857
|
" buildClientAppShellRegistration,",
|
|
@@ -853,16 +865,9 @@ export function createShellConfig(selectedModules) {
|
|
|
853
865
|
'import { getEnabledStarterModules } from "./modules";',
|
|
854
866
|
'import { shellRegistrationOverrides } from "./shell.overrides";',
|
|
855
867
|
"",
|
|
856
|
-
"const dashboardModuleRegistration: ShellModuleRegistration<ShellContextualAction> = {",
|
|
857
|
-
' key: "dashboard",',
|
|
858
|
-
' placement: "primary",',
|
|
859
|
-
' navItems: [{ href: "/dashboard", label: "Dashboard", icon: LayoutDashboard }],',
|
|
860
|
-
' toolbarRoutes: [{ surface: "dashboard", match: { exact: ["/dashboard"] } }],',
|
|
861
|
-
"};",
|
|
862
|
-
"",
|
|
863
868
|
"function getStarterModuleRegistrations() {",
|
|
864
869
|
' const enabled = new Set(getEnabledStarterModules().map((moduleConfig) => moduleConfig.key));',
|
|
865
|
-
" const registrations: ShellModuleRegistration<ShellContextualAction>[] = [
|
|
870
|
+
" const registrations: ShellModuleRegistration<ShellContextualAction>[] = [];",
|
|
866
871
|
"",
|
|
867
872
|
...registrationLines,
|
|
868
873
|
"",
|
|
@@ -900,7 +905,7 @@ export function createShellConfig(selectedModules) {
|
|
|
900
905
|
' key: "tools",',
|
|
901
906
|
' label: "Ferramentas",',
|
|
902
907
|
" icon: Wrench,",
|
|
903
|
-
' collapsedHref: enabledModules.find((moduleConfig) => moduleConfig.
|
|
908
|
+
' collapsedHref: enabledModules.find((moduleConfig) => moduleConfig.routeHref)?.routeHref || "/",',
|
|
904
909
|
" },",
|
|
905
910
|
" modules,",
|
|
906
911
|
" };",
|
|
@@ -1013,7 +1018,7 @@ async function writeClientStack(baseRoot, slug, dbInstallPlan, options = {}) {
|
|
|
1013
1018
|
: "Generated by create-bw-app in published mode.",
|
|
1014
1019
|
`Selected app modules: ${dbInstallPlan.selectedLabels.length > 0 ? dbInstallPlan.selectedLabels.join(", ") : "none"}.`,
|
|
1015
1020
|
`Resolved database stack: ${enabledModules.map((moduleKey) => getModuleLabel(moduleKey)).join(" -> ")}.`,
|
|
1016
|
-
"Platform always resolves to the Core + Admin database baseline; selecting Admin only controls whether the Admin
|
|
1021
|
+
"Platform always resolves to the Core + Admin database baseline; selecting Admin only controls whether the Admin package mount and wiring are scaffolded.",
|
|
1017
1022
|
"The database install order is resolved from supabase/module-registry.json.",
|
|
1018
1023
|
],
|
|
1019
1024
|
},
|
|
@@ -1240,7 +1245,9 @@ async function scaffoldPlatformProject({
|
|
|
1240
1245
|
for (const moduleDefinition of SELECTABLE_MODULES) {
|
|
1241
1246
|
if (!selectedModules.includes(moduleDefinition.key)) continue;
|
|
1242
1247
|
const moduleTemplateDir = path.join(TEMPLATE_ROOT, "modules", moduleDefinition.templateFolder);
|
|
1243
|
-
await
|
|
1248
|
+
if (await pathExists(moduleTemplateDir)) {
|
|
1249
|
+
await copyDirectory(moduleTemplateDir, targetDir);
|
|
1250
|
+
}
|
|
1244
1251
|
}
|
|
1245
1252
|
|
|
1246
1253
|
await fs.writeFile(
|
|
@@ -1258,6 +1265,7 @@ async function scaffoldPlatformProject({
|
|
|
1258
1265
|
)}\n`,
|
|
1259
1266
|
);
|
|
1260
1267
|
await fs.writeFile(path.join(targetDir, "next.config.ts"), createNextConfig({ template: "platform", selectedModules }));
|
|
1268
|
+
await fs.writeFile(path.join(targetDir, "app", "globals.css"), await createPlatformGlobalsCss(selectedModules));
|
|
1261
1269
|
await fs.writeFile(
|
|
1262
1270
|
path.join(targetDir, "config", "brand.ts"),
|
|
1263
1271
|
createPlatformBrandConfigFile({ slug: answers.slug, brandValues }),
|
package/src/remove.mjs
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
createAppContextFile,
|
|
14
14
|
createDbInstallPlan,
|
|
15
15
|
createNextConfig,
|
|
16
|
+
createPlatformGlobalsCss,
|
|
16
17
|
createPlatformModulesConfigFile,
|
|
17
18
|
createShellConfig,
|
|
18
19
|
getDbModuleRegistry,
|
|
@@ -59,6 +60,7 @@ export async function removeBrightwebModule(moduleKey, argvOptions = {}, runtime
|
|
|
59
60
|
});
|
|
60
61
|
const managedWrites = {
|
|
61
62
|
"next.config.ts": createNextConfig({ template: "platform", selectedModules: remainingModules }),
|
|
63
|
+
"app/globals.css": await createPlatformGlobalsCss(remainingModules),
|
|
62
64
|
"config/modules.ts": createPlatformModulesConfigFile(remainingModules),
|
|
63
65
|
"config/shell.ts": createShellConfig(remainingModules),
|
|
64
66
|
"docs/ai/app-context.json": createAppContextFile({ slug: appManifest.app.slug, template: "platform", selectedModules: remainingModules.filter((key) => key !== "orgs"), dbInstallPlan }),
|
package/src/update.mjs
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
createDbInstallPlan,
|
|
16
16
|
createNextConfig,
|
|
17
17
|
createPackageJson,
|
|
18
|
+
createPlatformGlobalsCss,
|
|
18
19
|
createPlatformModulesConfigFile,
|
|
19
20
|
createShellConfig,
|
|
20
21
|
detectPackageManager,
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
|
|
28
29
|
const MANAGED_PLATFORM_FILES = [
|
|
29
30
|
"next.config.ts",
|
|
31
|
+
path.join("app", "globals.css"),
|
|
30
32
|
path.join("config", "modules.ts"),
|
|
31
33
|
path.join("config", "shell.ts"),
|
|
32
34
|
path.join("docs", "ai", "app-context.json"),
|
|
@@ -490,6 +492,7 @@ export async function buildBrightwebAppUpdatePlan(argvOptions = {}, runtimeOptio
|
|
|
490
492
|
if (template === "platform") {
|
|
491
493
|
const canonicalConfigFiles = {
|
|
492
494
|
"next.config.ts": createNextConfig({ template: "platform", selectedModules: installedModules }),
|
|
495
|
+
[path.join("app", "globals.css")]: await createPlatformGlobalsCss(installedModules),
|
|
493
496
|
[path.join("config", "modules.ts")]: createPlatformModulesConfigFile(installedModules),
|
|
494
497
|
[path.join("config", "shell.ts")]: createShellConfig(installedModules),
|
|
495
498
|
[path.join("docs", "ai", "app-context.json")]: createAppContextFile({
|
package/template/base/AGENTS.md
CHANGED
|
@@ -1,31 +1,27 @@
|
|
|
1
1
|
# AGENTS.md
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This is a thin BrightWeb platform app. The app owns environment values and settings; reusable UI, domain behavior, and helpers belong in `@brightweblabs/*` packages.
|
|
4
4
|
|
|
5
5
|
## Start here
|
|
6
6
|
|
|
7
|
-
- `README.md`:
|
|
8
|
-
- `docs/ai/
|
|
9
|
-
- `
|
|
10
|
-
- `
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
-
|
|
14
|
-
- `config/modules.ts`: selected module set and runtime enablement.
|
|
15
|
-
- `config/client.ts`: starter-facing derived state used by the home page and setup surfaces.
|
|
16
|
-
- `.env.local`: runtime service values for local development.
|
|
7
|
+
- `README.md`: setup commands and mounted package routes.
|
|
8
|
+
- `docs/ai/app-context.json`: machine-readable module, path, and ownership summary.
|
|
9
|
+
- `config/brand.ts`: client identity and contact defaults.
|
|
10
|
+
- `config/modules.ts`: selected module set and route metadata.
|
|
11
|
+
- `config/shell.overrides.ts`: app-owned shell customizations.
|
|
12
|
+
- `app/theme.css`: app-owned theme token overrides.
|
|
13
|
+
- `.env.local`: runtime service values.
|
|
17
14
|
|
|
18
15
|
## Working rules
|
|
19
16
|
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
17
|
+
- Keep every `route.ts` as a direct package re-export; a `page.tsx` may instead import one package component and return only that mount.
|
|
18
|
+
- Do not add feature components, demos, hooks, data access, or helper libraries to this app.
|
|
19
|
+
- Put reusable behavior in the owning package, then mount its export here.
|
|
20
|
+
- Keep identity and theme changes in config and theme files.
|
|
21
|
+
- Check `config/modules.ts` before assuming an optional route exists. Projects currently has no default UI route.
|
|
25
22
|
|
|
26
23
|
## First validation pass
|
|
27
24
|
|
|
28
|
-
1.
|
|
29
|
-
2.
|
|
30
|
-
3.
|
|
31
|
-
4. Confirm `.env.local` contains real service values before debugging runtime behavior.
|
|
25
|
+
1. Fill `.env.local` with real service values.
|
|
26
|
+
2. Run the local type check or build.
|
|
27
|
+
3. Validate `/crm` and `/admin/users` only when their modules are enabled.
|