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 +31 -8
- package/package.json +1 -1
- package/src/constants.mjs +0 -3
- package/src/generator.mjs +99 -29
- package/template/base/AGENTS.md +26 -0
- package/template/base/app/page.tsx +1 -1
- package/template/base/config/bootstrap.ts +1 -1
- package/template/base/config/brand.ts +7 -9
- package/template/base/config/modules.ts +3 -11
- package/template/base/docs/ai/README.md +44 -0
- package/template/modules/admin/app/playground/admin/page.tsx +1 -1
- package/template/modules/crm/app/api/crm/contacts/route.ts +6 -0
- package/template/modules/crm/app/api/crm/organizations/route.ts +6 -0
- package/template/modules/crm/app/api/crm/owners/route.ts +6 -0
- package/template/modules/crm/app/api/crm/stats/route.ts +6 -0
package/README.md
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
# create-bw-app
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Scaffold a new BrightWeb app from either the `platform` or `site` starter.
|
|
4
4
|
|
|
5
|
-
##
|
|
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
|
-
|
|
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
|
|
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
|
|
31
|
-
- site apps include Next.js, Tailwind CSS, and local
|
|
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.
|
|
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
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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(
|
|
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`
|
|
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: "
|
|
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:
|
|
13
|
-
productName:
|
|
14
|
-
slug:
|
|
15
|
-
tagline:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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>
|