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.
Files changed (47) hide show
  1. package/README.md +6 -6
  2. package/package.json +1 -1
  3. package/src/add.mjs +2 -1
  4. package/src/app-manifest.mjs +1 -0
  5. package/src/constants.mjs +4 -9
  6. package/src/generator.mjs +64 -56
  7. package/src/remove.mjs +2 -0
  8. package/src/update.mjs +3 -0
  9. package/template/base/AGENTS.md +16 -20
  10. package/template/base/app/globals.css +5 -569
  11. package/template/base/app/theme.css +5 -0
  12. package/template/base/config/modules.ts +3 -5
  13. package/template/base/docs/ai/README.md +15 -41
  14. package/template/base/docs/ai/examples.md +13 -34
  15. package/template/base/public/brand/logo-dark.svg +2 -2
  16. package/template/base/public/brand/logo-light.svg +2 -2
  17. package/template/modules/admin/app/admin/users/page.tsx +2 -0
  18. package/template/modules/admin/app/api/admin/users/roles/route.ts +1 -6
  19. package/template/modules/admin/app/api/admin/users/route.ts +1 -6
  20. package/template/modules/crm/app/api/crm/contacts/route.ts +3 -18
  21. package/template/modules/crm/app/api/crm/organizations/route.ts +1 -8
  22. package/template/modules/crm/app/api/crm/owners/route.ts +1 -8
  23. package/template/modules/crm/app/api/crm/stats/route.ts +1 -8
  24. package/template/modules/crm/app/api/crm/timeline/route.ts +1 -8
  25. package/template/site/base/AGENTS.md +6 -19
  26. package/template/site/base/docs/ai/README.md +6 -33
  27. package/template/site/base/docs/ai/examples.md +6 -28
  28. package/template/base/app/bootstrap/page.tsx +0 -75
  29. package/template/base/app/page.tsx +0 -145
  30. package/template/base/app/playground/auth/page.tsx +0 -5
  31. package/template/base/app/playground/layout.tsx +0 -41
  32. package/template/base/app/preview/app-shell/page.tsx +0 -11
  33. package/template/base/components/app-shell-preview.tsx +0 -185
  34. package/template/base/components/auth-playground.tsx +0 -112
  35. package/template/base/config/bootstrap.ts +0 -131
  36. package/template/base/config/client.ts +0 -18
  37. package/template/base/config/env.ts +0 -100
  38. package/template/base/lib/email/resend-base.ts +0 -13
  39. package/template/modules/admin/app/playground/admin/page.tsx +0 -102
  40. package/template/modules/crm/app/api/crm/_shared/create-module-route-handler.ts +0 -13
  41. package/template/modules/projects/app/playground/projects/page.tsx +0 -93
  42. package/template/site/base/app/page.tsx +0 -165
  43. package/template/site/base/components/ui/badge.tsx +0 -28
  44. package/template/site/base/components/ui/button.tsx +0 -52
  45. package/template/site/base/components/ui/card.tsx +0 -28
  46. package/template/site/base/components.json +0 -17
  47. 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 module wiring and starter overlays, and appends migrations.
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 starter files and only rewrites them with `--refresh-starters`
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 module starter surfaces
73
- - platform apps include a local `components/` folder for app-owned UI alongside the shared BrightWeb packages
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, Tailwind CSS v4, and local component primitives
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 starter UI and package wiring, not whether the Admin database layer exists.
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-bw-app",
3
3
  "private": false,
4
- "version": "0.12.0",
4
+ "version": "0.13.0",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "create-bw-app": "bin/create-bw-app.mjs",
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 }),
@@ -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: "Standalone Next.js + Tailwind site starter with a local UI layer.",
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/playground/admin/page.tsx",
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.3.5",
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 starter route files from the latest template
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 starter UI and package wiring are scaffolded.");
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
- " playgroundHref?: string;",
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
- ' playgroundHref: "/crm",',
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
- ' playgroundHref: "/playground/admin",',
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
- "/bootstrap",
444
- "/preview/app-shell",
445
- "/playground/auth",
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
- "## Starter routes",
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
- "- Local shadcn-style component primitives",
541
+ "- App-owned settings and theme tokens",
546
542
  "",
547
543
  "## Local setup",
548
544
  "",
549
545
  ...localSteps,
550
546
  "",
551
- "## Starter surfaces",
547
+ "## Package mounts",
552
548
  "",
553
549
  ...getSiteStarterRoutes().map((route) => `- \`${route}\``),
554
550
  "",
555
- "Edit `config/site.ts` to change the site name, copy, and public links.",
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
- editConfigBeforeCopyTweaks: true,
619
- keepUiPrimitiveChangesLocal: true,
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
- preferAppLevelCompositionOverPackageForks: true,
687
- treatStarterRoutesAsRemovable: true,
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 { LayoutDashboard, Wrench } from "lucide-react";',
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>[] = [dashboardModuleRegistration];",
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.playgroundHref)?.playgroundHref || "/",',
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 starter UI and package wiring are scaffolded.",
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 copyDirectory(moduleTemplateDir, targetDir);
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({
@@ -1,31 +1,27 @@
1
1
  # AGENTS.md
2
2
 
3
- This generated project is a BrightWeb platform starter. Use this file as the local entrypoint for AI agents working inside the app.
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`: local setup commands and starter routes.
8
- - `docs/ai/README.md`: app-specific routing guide for agents.
9
- - `docs/ai/examples.md`: common setup and customization flows.
10
- - `docs/ai/app-context.json`: machine-readable app summary for quick discovery.
11
- - `components/`: local app components used by starter routes and future product surfaces.
12
- - `config/brand.ts`: client identity, naming, and contact defaults.
13
- - `app/globals.css`: global design tokens, theme mapping, and shared visual styling.
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
- - Treat `/bootstrap`, `/preview/app-shell`, and `/playground/*` as starter validation surfaces. They are app-owned and can be removed after setup if links and references are cleaned up too.
21
- - Keep identity/contact in `config/brand.ts`, and keep all color/theme tokens in `app/globals.css`.
22
- - Check `config/modules.ts` before assuming CRM, Projects, or Admin routes exist.
23
- - Prefer composing app-level routes and config before forking logic from `@brightweblabs/*` packages.
24
- - Keep edits local to this app unless the change is intentionally shared across multiple BrightWeb projects.
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. Run the local dev server from this project or workspace.
29
- 2. Open `/`, `/bootstrap`, `/preview/app-shell`, and `/playground/auth`.
30
- 3. If optional modules are enabled, open the matching `/playground/*` route for each one.
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.