create-bw-app 0.7.0 → 0.9.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 CHANGED
@@ -1,22 +1,26 @@
1
1
  # create-bw-app
2
2
 
3
- Create a new BrightWeb app from either the platform or site starter.
3
+ Scaffold a new BrightWeb app from either the `platform` or `site` starter.
4
4
 
5
- ## Local workspace usage
5
+ ## Workspace usage
6
6
 
7
7
  From the BrightWeb platform repo root:
8
8
 
9
9
  ```bash
10
10
  pnpm create:client
11
+ pnpm create:client -- --help
11
12
  pnpm create:client -- --template site
12
13
  ```
13
14
 
14
- ## Future published usage
15
+ The workspace wrapper delegates to this package with `workspace:*` dependency wiring and BrightWeb-specific output rules.
16
+
17
+ ## Published usage
15
18
 
16
19
  Once this package is published to npm:
17
20
 
18
21
  ```bash
19
22
  pnpm dlx create-bw-app
23
+ pnpm dlx create-bw-app --template site
20
24
  npm create bw-app@latest
21
25
  ```
22
26
 
@@ -24,11 +28,30 @@ npm create bw-app@latest
24
28
 
25
29
  - prompts for app type: `platform` or `site`
26
30
  - prompts for project name
27
- - prompts for optional modules with a checkbox list when using the platform template
31
+ - prompts for optional platform modules: `admin`, `crm`, and `projects`
28
32
  - prompts to install dependencies immediately
29
- - copies a clean Next.js starter template
30
- - platform apps include BrightWeb auth, shell, and optional business modules
31
- - site apps include Next.js, Tailwind CSS, and local shadcn-style component primitives
33
+ - copies a clean Next.js App Router starter template
34
+ - platform apps include BrightWeb auth, shell wiring, and optional module starter surfaces
35
+ - site apps include Next.js, Tailwind CSS v4, and local component primitives
32
36
  - writes `package.json`, `next.config.ts`, `.gitignore`, and `README.md` for both templates
33
- - platform apps also write `.env.example` and `.env.local`
37
+ - platform apps also write `.env.local`, `AGENTS.md`, `docs/ai/README.md`, and generated config files for brand and module state
34
38
  - supports repo-local `workspace:*` wiring and future published dependency wiring
39
+
40
+ ## Workspace mode extras
41
+
42
+ When this package runs in BrightWeb workspace mode, it can:
43
+
44
+ - write the new app under `apps/<slug>`
45
+ - keep internal dependencies on `workspace:*`
46
+ - create `supabase/clients/<slug>/stack.json`
47
+ - create a client-only migrations folder so database planning stays aligned with scaffolded modules
48
+
49
+ 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.
50
+
51
+ ## Related references
52
+
53
+ - `packages/create-bw-app/src/generator.mjs`
54
+ - `packages/create-bw-app/src/constants.mjs`
55
+ - `packages/create-bw-app/template/base`
56
+ - `packages/create-bw-app/template/site/base`
57
+ - `packages/create-bw-app/template/modules`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-bw-app",
3
3
  "private": false,
4
- "version": "0.7.0",
4
+ "version": "0.9.0",
5
5
  "type": "module",
6
6
  "bin": "bin/create-bw-app.mjs",
7
7
  "files": [
package/src/constants.mjs CHANGED
@@ -20,21 +20,18 @@ export const SELECTABLE_MODULES = [
20
20
  label: "CRM",
21
21
  packageName: "@brightweblabs/module-crm",
22
22
  templateFolder: "crm",
23
- envKey: "NEXT_PUBLIC_ENABLE_CRM",
24
23
  },
25
24
  {
26
25
  key: "projects",
27
26
  label: "Projects",
28
27
  packageName: "@brightweblabs/module-projects",
29
28
  templateFolder: "projects",
30
- envKey: "NEXT_PUBLIC_ENABLE_PROJECTS",
31
29
  },
32
30
  {
33
31
  key: "admin",
34
32
  label: "Admin",
35
33
  packageName: "@brightweblabs/module-admin",
36
34
  templateFolder: "admin",
37
- envKey: "NEXT_PUBLIC_ENABLE_ADMIN",
38
35
  },
39
36
  ];
40
37
 
package/src/generator.mjs CHANGED
@@ -189,7 +189,7 @@ function createDbInstallPlan({ selectedModules, workspaceMode, registry }) {
189
189
  const notes = [];
190
190
 
191
191
  if (!selectedModules.includes("admin") && resolvedOrder.includes("admin")) {
192
- notes.push("Admin governance stays enabled for platform auth/RBAC even if the admin UI module is not selected.");
192
+ 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.");
193
193
  }
194
194
 
195
195
  for (const moduleKey of resolvedOrder) {
@@ -256,13 +256,6 @@ async function getVersionMap(workspaceRoot) {
256
256
  return versionMap;
257
257
  }
258
258
 
259
- function createModuleFlags(selectedModules) {
260
- const selected = new Set(selectedModules);
261
- return Object.fromEntries(
262
- SELECTABLE_MODULES.map((moduleDefinition) => [moduleDefinition.key, selected.has(moduleDefinition.key)]),
263
- );
264
- }
265
-
266
259
  function createDerivedBrandValues(slug) {
267
260
  const projectName = titleizeSlug(slug);
268
261
 
@@ -276,7 +269,94 @@ function createDerivedBrandValues(slug) {
276
269
  };
277
270
  }
278
271
 
279
- function createEnvFileContent({ slug, brandValues, moduleFlags }) {
272
+ function createPlatformBrandConfigFile({ slug, brandValues }) {
273
+ return [
274
+ "export type StarterBrandConfig = {",
275
+ " companyName: string;",
276
+ " productName: string;",
277
+ " slug: string;",
278
+ " tagline: string;",
279
+ " contactEmail: string;",
280
+ " supportEmail: string;",
281
+ " primaryHex: string;",
282
+ "};",
283
+ "",
284
+ "export const starterBrandConfig: StarterBrandConfig = {",
285
+ ` companyName: ${JSON.stringify(brandValues.companyName)},`,
286
+ ` productName: ${JSON.stringify(brandValues.productName)},`,
287
+ ` slug: ${JSON.stringify(slug)},`,
288
+ ` tagline: ${JSON.stringify(brandValues.tagline)},`,
289
+ ` contactEmail: ${JSON.stringify(brandValues.contactEmail)},`,
290
+ ` supportEmail: ${JSON.stringify(brandValues.supportEmail)},`,
291
+ ` primaryHex: ${JSON.stringify(brandValues.primaryHex)},`,
292
+ "};",
293
+ "",
294
+ ].join("\n");
295
+ }
296
+
297
+ function createPlatformModulesConfigFile(selectedModules) {
298
+ const selected = new Set(selectedModules);
299
+
300
+ return [
301
+ 'export type StarterModuleKey = "core-auth" | "crm" | "projects" | "admin";',
302
+ "",
303
+ "export type StarterModuleConfig = {",
304
+ " key: StarterModuleKey;",
305
+ " label: string;",
306
+ " description: string;",
307
+ " enabled: boolean;",
308
+ " packageName: string;",
309
+ " playgroundHref?: string;",
310
+ ' placement: "core" | "primary" | "admin";',
311
+ "};",
312
+ "",
313
+ "export const starterModuleConfig: StarterModuleConfig[] = [",
314
+ " {",
315
+ ' key: "core-auth",',
316
+ ' label: "Core Auth",',
317
+ ' description: "Login, reset-password, callback URLs, and shared auth validation utilities.",',
318
+ " enabled: true,",
319
+ ' packageName: "@brightweblabs/core-auth",',
320
+ ' playgroundHref: "/playground/auth",',
321
+ ' placement: "core",',
322
+ " },",
323
+ " {",
324
+ ' key: "crm",',
325
+ ' label: "CRM",',
326
+ ' description: "Contacts, marketing audience, and CRM server/data layer.",',
327
+ ` enabled: ${String(selected.has("crm"))},`,
328
+ ' packageName: "@brightweblabs/module-crm",',
329
+ ' playgroundHref: "/playground/crm",',
330
+ ' placement: "primary",',
331
+ " },",
332
+ " {",
333
+ ' key: "projects",',
334
+ ' label: "Projects",',
335
+ ' description: "Project portfolio, detail routes, and work-management server logic.",',
336
+ ` enabled: ${String(selected.has("projects"))},`,
337
+ ' packageName: "@brightweblabs/module-projects",',
338
+ ' playgroundHref: "/playground/projects",',
339
+ ' placement: "primary",',
340
+ " },",
341
+ " {",
342
+ ' key: "admin",',
343
+ ' label: "Admin",',
344
+ ' description: "User role governance, admin tools, and access-control surfaces.",',
345
+ ` enabled: ${String(selected.has("admin"))},`,
346
+ ' packageName: "@brightweblabs/module-admin",',
347
+ ' playgroundHref: "/playground/admin",',
348
+ ' placement: "admin",',
349
+ " },",
350
+ "];",
351
+ "",
352
+ "export function getEnabledStarterModules() {",
353
+ " return starterModuleConfig.filter((moduleConfig) => moduleConfig.enabled);",
354
+ "}",
355
+ "",
356
+ ].join("\n");
357
+ }
358
+
359
+ function createEnvFileContent() {
280
360
  return [
281
361
  "NEXT_PUBLIC_APP_URL=http://localhost:3000",
282
362
  "NEXT_PUBLIC_SUPABASE_URL=",
@@ -284,18 +364,6 @@ function createEnvFileContent({ slug, brandValues, moduleFlags }) {
284
364
  "SUPABASE_SERVICE_ROLE_KEY=",
285
365
  "RESEND_API_KEY=",
286
366
  "",
287
- `NEXT_PUBLIC_CLIENT_COMPANY_NAME=${brandValues.companyName}`,
288
- `NEXT_PUBLIC_CLIENT_PRODUCT_NAME=${brandValues.productName}`,
289
- `NEXT_PUBLIC_CLIENT_SLUG=${slug}`,
290
- `NEXT_PUBLIC_CLIENT_TAGLINE=${brandValues.tagline}`,
291
- `NEXT_PUBLIC_CLIENT_CONTACT_EMAIL=${brandValues.contactEmail}`,
292
- `NEXT_PUBLIC_CLIENT_SUPPORT_EMAIL=${brandValues.supportEmail}`,
293
- `NEXT_PUBLIC_CLIENT_PRIMARY_HEX=${brandValues.primaryHex}`,
294
- "",
295
- `NEXT_PUBLIC_ENABLE_CRM=${String(moduleFlags.crm)}`,
296
- `NEXT_PUBLIC_ENABLE_PROJECTS=${String(moduleFlags.projects)}`,
297
- `NEXT_PUBLIC_ENABLE_ADMIN=${String(moduleFlags.admin)}`,
298
- "",
299
367
  ].join("\n");
300
368
  }
301
369
 
@@ -333,9 +401,8 @@ function createGitignore() {
333
401
  "yarn-error.log*",
334
402
  ".pnpm-debug.log*",
335
403
  "",
336
- "# env files (can opt-in for committing if needed)",
404
+ "# env files",
337
405
  ".env*",
338
- "!.env.example",
339
406
  "",
340
407
  "# vercel",
341
408
  ".vercel",
@@ -363,12 +430,12 @@ function createPlatformReadme({
363
430
 
364
431
  const localSteps = workspaceMode
365
432
  ? [
366
- "1. Review `.env.example`, then fill `.env.local` with real service credentials.",
433
+ "1. Review `.env.local` and fill in real service credentials.",
367
434
  "2. Run `pnpm install` from the BrightWeb workspace root.",
368
435
  `3. Run \`pnpm --filter ${slug} dev\`.`,
369
436
  ]
370
437
  : [
371
- "1. Review `.env.example`, then fill `.env.local` with real service credentials.",
438
+ "1. Review `.env.local` and fill in real service credentials.",
372
439
  `2. Run \`${packageManager} install\`.`,
373
440
  `3. Run \`${packageManager} dev\`.`,
374
441
  ];
@@ -716,7 +783,7 @@ async function writeWorkspaceClientStack(workspaceRoot, slug, selectedModules) {
716
783
  "Generated by create-bw-app in workspace mode.",
717
784
  `Selected app modules: ${dbInstallPlan.selectedLabels.length > 0 ? dbInstallPlan.selectedLabels.join(", ") : "none"}.`,
718
785
  `Resolved database stack: ${enabledModules.map((moduleKey) => getModuleLabel(moduleKey)).join(" -> ")}.`,
719
- "Admin governance stays enabled for platform auth/RBAC even if the admin UI module is not selected.",
786
+ "Platform always resolves to the Core + Admin database baseline; selecting Admin only controls whether the Admin starter UI and package wiring are scaffolded.",
720
787
  "The database install order is resolved from supabase/module-registry.json.",
721
788
  ],
722
789
  },
@@ -871,7 +938,6 @@ async function scaffoldPlatformProject({
871
938
  answers,
872
939
  dbInstallPlan,
873
940
  }) {
874
- const moduleFlags = createModuleFlags(selectedModules);
875
941
  const brandValues = createDerivedBrandValues(answers.slug);
876
942
  const baseTemplateDir = path.join(TEMPLATE_ROOT, "base");
877
943
 
@@ -899,11 +965,15 @@ async function scaffoldPlatformProject({
899
965
  )}\n`,
900
966
  );
901
967
  await fs.writeFile(path.join(targetDir, "next.config.ts"), createNextConfig({ template: "platform", selectedModules }));
968
+ await fs.writeFile(
969
+ path.join(targetDir, "config", "brand.ts"),
970
+ createPlatformBrandConfigFile({ slug: answers.slug, brandValues }),
971
+ );
972
+ await fs.writeFile(path.join(targetDir, "config", "modules.ts"), createPlatformModulesConfigFile(selectedModules));
902
973
  await fs.writeFile(path.join(targetDir, "config", "shell.ts"), createShellConfig(selectedModules));
903
974
 
904
- const envFileContent = createEnvFileContent({ slug: answers.slug, brandValues, moduleFlags });
975
+ const envFileContent = createEnvFileContent();
905
976
 
906
- await fs.writeFile(path.join(targetDir, ".env.example"), envFileContent);
907
977
  await fs.writeFile(path.join(targetDir, ".env.local"), envFileContent);
908
978
  await fs.writeFile(path.join(targetDir, ".gitignore"), createGitignore());
909
979
  await fs.writeFile(
@@ -0,0 +1,26 @@
1
+ # AGENTS.md
2
+
3
+ This generated project is a BrightWeb platform starter. Use this file as the local entrypoint for AI agents working inside the app.
4
+
5
+ ## Start here
6
+
7
+ - `README.md`: local setup commands and starter routes.
8
+ - `docs/ai/README.md`: app-specific routing guide for agents.
9
+ - `config/brand.ts`: client identity, naming, and contact defaults.
10
+ - `config/modules.ts`: selected module set and runtime enablement.
11
+ - `config/client.ts`: starter-facing derived state used by the home page and setup surfaces.
12
+ - `.env.local`: runtime service values for local development.
13
+
14
+ ## Working rules
15
+
16
+ - 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.
17
+ - Check `config/modules.ts` before assuming CRM, Projects, or Admin routes exist.
18
+ - Prefer composing app-level routes and config before forking logic from `@brightweblabs/*` packages.
19
+ - Keep edits local to this app unless the change is intentionally shared across multiple BrightWeb projects.
20
+
21
+ ## First validation pass
22
+
23
+ 1. Run the local dev server from this project or workspace.
24
+ 2. Open `/`, `/bootstrap`, `/preview/app-shell`, and `/playground/auth`.
25
+ 3. If optional modules are enabled, open the matching `/playground/*` route for each one.
26
+ 4. Confirm `.env.local` contains real service values before debugging runtime behavior.
@@ -115,7 +115,7 @@ export default function HomePage() {
115
115
  <li>`config/brand.ts` for client identity and contact details.</li>
116
116
  <li>`config/modules.ts` for enabled platform modules.</li>
117
117
  <li>`config/env.ts` for infra requirements and readiness checks.</li>
118
- <li>`.env.local` from `.env.example` for per-client secrets and flags.</li>
118
+ <li>`.env.local` for per-client service credentials and local runtime overrides.</li>
119
119
  </ul>
120
120
  </div>
121
121
  </article>
@@ -69,7 +69,7 @@ export function getStarterBootstrapChecklist() {
69
69
  {
70
70
  label: "Create per-client environment variables",
71
71
  done: config.envReadiness.allReady,
72
- detail: "Copy `.env.example` into `.env.local` and fill the real values.",
72
+ detail: "Fill `.env.local` with the real service values for this client.",
73
73
  },
74
74
  ],
75
75
  };
@@ -9,13 +9,11 @@ export type StarterBrandConfig = {
9
9
  };
10
10
 
11
11
  export const starterBrandConfig: StarterBrandConfig = {
12
- companyName: process.env.NEXT_PUBLIC_CLIENT_COMPANY_NAME?.trim() || "Starter Client",
13
- productName: process.env.NEXT_PUBLIC_CLIENT_PRODUCT_NAME?.trim() || "Operations Platform",
14
- slug: process.env.NEXT_PUBLIC_CLIENT_SLUG?.trim() || "starter-client",
15
- tagline:
16
- process.env.NEXT_PUBLIC_CLIENT_TAGLINE?.trim()
17
- || "A configurable Brightweb starter app for shipping new client instances without rebuilding the platform.",
18
- contactEmail: process.env.NEXT_PUBLIC_CLIENT_CONTACT_EMAIL?.trim() || "hello@example.com",
19
- supportEmail: process.env.NEXT_PUBLIC_CLIENT_SUPPORT_EMAIL?.trim() || "support@example.com",
20
- primaryHex: process.env.NEXT_PUBLIC_CLIENT_PRIMARY_HEX?.trim() || "#1f7a45",
12
+ companyName: "Starter Client",
13
+ productName: "Operations Platform",
14
+ slug: "starter-client",
15
+ tagline: "A configurable Brightweb starter app for shipping new client instances without rebuilding the platform.",
16
+ contactEmail: "hello@example.com",
17
+ supportEmail: "support@example.com",
18
+ primaryHex: "#1f7a45",
21
19
  };
@@ -10,14 +10,6 @@ export type StarterModuleConfig = {
10
10
  placement: "core" | "primary" | "admin";
11
11
  };
12
12
 
13
- function envFlag(value: string | undefined, defaultValue: boolean) {
14
- if (typeof value !== "string") return defaultValue;
15
- const normalized = value.trim().toLowerCase();
16
- if (["1", "true", "yes", "on"].includes(normalized)) return true;
17
- if (["0", "false", "no", "off"].includes(normalized)) return false;
18
- return defaultValue;
19
- }
20
-
21
13
  export const starterModuleConfig: StarterModuleConfig[] = [
22
14
  {
23
15
  key: "core-auth",
@@ -32,7 +24,7 @@ export const starterModuleConfig: StarterModuleConfig[] = [
32
24
  key: "crm",
33
25
  label: "CRM",
34
26
  description: "Contacts, marketing audience, and CRM server/data layer.",
35
- enabled: envFlag(process.env.NEXT_PUBLIC_ENABLE_CRM, true),
27
+ enabled: true,
36
28
  packageName: "@brightweblabs/module-crm",
37
29
  playgroundHref: "/playground/crm",
38
30
  placement: "primary",
@@ -41,7 +33,7 @@ export const starterModuleConfig: StarterModuleConfig[] = [
41
33
  key: "projects",
42
34
  label: "Projects",
43
35
  description: "Project portfolio, detail routes, and work-management server logic.",
44
- enabled: envFlag(process.env.NEXT_PUBLIC_ENABLE_PROJECTS, true),
36
+ enabled: true,
45
37
  packageName: "@brightweblabs/module-projects",
46
38
  playgroundHref: "/playground/projects",
47
39
  placement: "primary",
@@ -50,7 +42,7 @@ export const starterModuleConfig: StarterModuleConfig[] = [
50
42
  key: "admin",
51
43
  label: "Admin",
52
44
  description: "User role governance, admin tools, and access-control surfaces.",
53
- enabled: envFlag(process.env.NEXT_PUBLIC_ENABLE_ADMIN, true),
45
+ enabled: true,
54
46
  packageName: "@brightweblabs/module-admin",
55
47
  playgroundHref: "/playground/admin",
56
48
  placement: "admin",
@@ -0,0 +1,44 @@
1
+ # Agent Guide
2
+
3
+ This file is the local routing guide for AI agents working inside a generated BrightWeb platform app.
4
+
5
+ It is intentionally app-scoped. It explains the generated project you are in, not the maintainer-only BrightWeb monorepo internals.
6
+
7
+ ## Project shape
8
+
9
+ This app is a normal Next.js App Router project with BrightWeb runtime wiring layered on top.
10
+
11
+ - `app/`: route tree, layouts, pages, starter previews, and playground routes.
12
+ - `config/`: generated app configuration for brand, env readiness, enabled modules, bootstrap content, and shell registration.
13
+ - `public/brand/`: starter logos used by the shell lockups.
14
+ - `.env.local`: local service configuration for Supabase, Resend, and runtime URLs.
15
+
16
+ ## Fast routing map
17
+
18
+ - `README.md`: first-run setup steps.
19
+ - `config/brand.ts`: client name, product name, support inboxes, and brand color.
20
+ - `config/modules.ts`: module metadata and enablement flags for CRM, Projects, and Admin.
21
+ - `config/client.ts`: aggregated state consumed by starter pages.
22
+ - `config/bootstrap.ts`: bootstrap checklist content for `/bootstrap`.
23
+ - `config/shell.ts`: app-shell registration and navigation wiring.
24
+ - `app/page.tsx`: starter landing page for the generated app.
25
+ - `app/bootstrap/page.tsx`: setup checklist surface.
26
+ - `app/preview/app-shell/page.tsx`: shell preview validation route.
27
+ - `app/playground/auth/page.tsx`: auth validation route.
28
+ - `app/playground/*`: optional module playgrounds when those modules were selected at scaffold time.
29
+
30
+ ## Editing strategy
31
+
32
+ - Change client identity first in `config/brand.ts`.
33
+ - Check module presence in `config/modules.ts` before editing or creating module-specific routes.
34
+ - Use `config/shell.ts` when navigation or toolbar behavior needs to change.
35
+ - Use `config/bootstrap.ts` and `config/client.ts` when the setup checklist or readiness messaging is wrong.
36
+ - Keep starter validation routes until the real product routes replace their purpose.
37
+
38
+ ## Validation checklist
39
+
40
+ 1. Confirm `.env.local` is populated with real values.
41
+ 2. Run the app locally.
42
+ 3. Validate `/`, `/bootstrap`, `/preview/app-shell`, and `/playground/auth`.
43
+ 4. Validate the playground route for each enabled optional module.
44
+ 5. If a starter route is removed, also remove any links or config references that still point to it.
@@ -20,7 +20,7 @@ export default async function AdminPlaygroundPage() {
20
20
  <p className="eyebrow">Admin Module</p>
21
21
  <h1>Admin users and roles playground</h1>
22
22
  <p className="muted">
23
- This route previews the shared admin governance module without relying on the BeGreen client app.
23
+ This route previews the shared admin governance module without relying on any client-specific app.
24
24
  </p>
25
25
  </div>
26
26
  </article>
@@ -0,0 +1,6 @@
1
+ export const dynamic = "force-dynamic";
2
+
3
+ export async function GET(request: Request) {
4
+ const { handleCrmContactsGetRequest } = await import("@brightweblabs/module-crm");
5
+ return handleCrmContactsGetRequest(request);
6
+ }
@@ -0,0 +1,6 @@
1
+ export const dynamic = "force-dynamic";
2
+
3
+ export async function GET(request: Request) {
4
+ const { handleCrmOrganizationsGetRequest } = await import("@brightweblabs/module-crm");
5
+ return handleCrmOrganizationsGetRequest(request);
6
+ }
@@ -0,0 +1,6 @@
1
+ export const dynamic = "force-dynamic";
2
+
3
+ export async function GET(request: Request) {
4
+ const { handleCrmOwnersGetRequest } = await import("@brightweblabs/module-crm");
5
+ return handleCrmOwnersGetRequest(request);
6
+ }
@@ -0,0 +1,6 @@
1
+ export const dynamic = "force-dynamic";
2
+
3
+ export async function GET(request: Request) {
4
+ const { handleCrmStatsGetRequest } = await import("@brightweblabs/module-crm");
5
+ return handleCrmStatsGetRequest(request);
6
+ }