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
|
@@ -1,42 +1,21 @@
|
|
|
1
1
|
# Agent Examples
|
|
2
2
|
|
|
3
|
-
Use these workflows after reading `AGENTS.md`, `docs/ai/README.md`, and `docs/ai/app-context.json`.
|
|
4
|
-
|
|
5
3
|
## First local setup
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- Review `app/globals.css` and confirm brand tokens map to the intended visual system.
|
|
12
|
-
- Review `config/modules.ts` before touching module routes.
|
|
13
|
-
- Run the local dev server for this app or workspace.
|
|
14
|
-
- Validate `/`, `/bootstrap`, `/preview/app-shell`, and `/playground/auth`.
|
|
15
|
-
- Validate `/crm`, `/playground/projects`, and `/playground/admin` only when those modules are enabled.
|
|
16
|
-
|
|
17
|
-
## Change brand identity
|
|
18
|
-
|
|
19
|
-
Goal: update the starter to the real client name and support details.
|
|
20
|
-
|
|
21
|
-
- Edit `config/brand.ts`.
|
|
22
|
-
- Edit `app/globals.css` when palette or theme token mapping needs to change.
|
|
23
|
-
- Move route-specific presentation into `components/` when the home or preview surfaces need app-owned UI.
|
|
24
|
-
- Check `config/client.ts` or `config/bootstrap.ts` if starter copy still references old defaults.
|
|
25
|
-
- Validate the home page and `/preview/app-shell` after the change.
|
|
26
|
-
|
|
27
|
-
## Replace starter routes with product routes
|
|
28
|
-
|
|
29
|
-
Goal: move from validation surfaces to product-owned pages.
|
|
5
|
+
- Fill `.env.local`.
|
|
6
|
+
- Review `config/brand.ts`, `config/modules.ts`, and `app/theme.css`.
|
|
7
|
+
- Run the app build.
|
|
8
|
+
- Validate the package routes listed in `docs/ai/app-context.json`.
|
|
30
9
|
|
|
31
|
-
|
|
32
|
-
- Keep reusable route UI in `components/` so the app follows the expected Next.js folder split.
|
|
33
|
-
- Update `config/shell.overrides.ts` if navigation or toolbar behavior changes.
|
|
34
|
-
- Remove `/bootstrap`, `/preview/app-shell`, or `/playground/*` only after links and config references are cleaned up.
|
|
10
|
+
## Add a product surface
|
|
35
11
|
|
|
36
|
-
|
|
12
|
+
- Implement and export the surface from its `@brightweblabs/*` package.
|
|
13
|
+
- Add any package contract entry and tests there.
|
|
14
|
+
- Add a route file containing only a direct package re-export.
|
|
15
|
+
- Register the route in module and shell settings.
|
|
37
16
|
|
|
38
|
-
|
|
17
|
+
## Customize the shell
|
|
39
18
|
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
19
|
+
- Keep package registrations intact.
|
|
20
|
+
- Put app-specific href or visibility changes in `config/shell.overrides.ts`.
|
|
21
|
+
- Rebuild and verify the affected mounted route.
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
<rect width="44" height="44" rx="12" fill="#F5F4EC"/>
|
|
3
3
|
<path d="M12 32V12H22.2C26.18 12 28.52 13.94 28.52 17.06C28.52 19.04 27.56 20.48 25.86 21.22C28.08 21.88 29.4 23.54 29.4 25.94C29.4 29.7 26.68 32 22.22 32H12ZM16.42 20.04H21.48C23.1 20.04 24.02 19.24 24.02 17.86C24.02 16.46 23.1 15.68 21.48 15.68H16.42V20.04ZM16.42 28.28H21.96C23.82 28.28 24.86 27.42 24.86 25.86C24.86 24.32 23.82 23.46 21.96 23.46H16.42V28.28Z" fill="#102015"/>
|
|
4
4
|
<path d="M30.2 12H34.58L36.72 23.86L39.32 12H43.1L39 32H34.88L32.38 19.64L29.9 32H25.82L25.1 28.56H29.1L30.2 12Z" fill="#2C8A53"/>
|
|
5
|
-
<text x="58" y="19" fill="#F5F4EC" font-family="
|
|
6
|
-
<text x="58" y="33" fill="#C8D0C9" font-family="'
|
|
5
|
+
<text x="58" y="19" fill="#F5F4EC" font-family="'Segoe UI', Arial, sans-serif" font-size="11" letter-spacing="2">BRIGHTWEB</text>
|
|
6
|
+
<text x="58" y="33" fill="#C8D0C9" font-family="'Segoe UI', Arial, sans-serif" font-size="15">starter client</text>
|
|
7
7
|
</svg>
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
<rect width="44" height="44" rx="12" fill="#13251A"/>
|
|
3
3
|
<path d="M12 32V12H22.2C26.18 12 28.52 13.94 28.52 17.06C28.52 19.04 27.56 20.48 25.86 21.22C28.08 21.88 29.4 23.54 29.4 25.94C29.4 29.7 26.68 32 22.22 32H12ZM16.42 20.04H21.48C23.1 20.04 24.02 19.24 24.02 17.86C24.02 16.46 23.1 15.68 21.48 15.68H16.42V20.04ZM16.42 28.28H21.96C23.82 28.28 24.86 27.42 24.86 25.86C24.86 24.32 23.82 23.46 21.96 23.46H16.42V28.28Z" fill="#F5F4EC"/>
|
|
4
4
|
<path d="M30.2 12H34.58L36.72 23.86L39.32 12H43.1L39 32H34.88L32.38 19.64L29.9 32H25.82L25.1 28.56H29.1L30.2 12Z" fill="#71C48B"/>
|
|
5
|
-
<text x="58" y="19" fill="#13251A" font-family="
|
|
6
|
-
<text x="58" y="33" fill="#516252" font-family="'
|
|
5
|
+
<text x="58" y="19" fill="#13251A" font-family="'Segoe UI', Arial, sans-serif" font-size="11" letter-spacing="2">BRIGHTWEB</text>
|
|
6
|
+
<text x="58" y="33" fill="#516252" font-family="'Segoe UI', Arial, sans-serif" font-size="15">starter client</text>
|
|
7
7
|
</svg>
|
|
@@ -1,6 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
export async function POST(request: Request) {
|
|
4
|
-
const { handleAdminUsersRoleChangeRequest } = await import("@brightweblabs/module-admin");
|
|
5
|
-
return handleAdminUsersRoleChangeRequest(request);
|
|
6
|
-
}
|
|
1
|
+
export { handleAdminUsersRoleChangeRequest as POST } from "@brightweblabs/module-admin";
|
|
@@ -1,6 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
export async function GET(request: Request) {
|
|
4
|
-
const { handleAdminUsersGetRequest } = await import("@brightweblabs/module-admin");
|
|
5
|
-
return handleAdminUsersGetRequest(request);
|
|
6
|
-
}
|
|
1
|
+
export { handleAdminUsersGetRequest as GET } from "@brightweblabs/module-admin";
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
export const GET = createModuleRouteHandler(
|
|
6
|
-
() => import("@brightweblabs/module-crm"),
|
|
7
|
-
"handleCrmContactsGetRequest",
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
export const POST = createModuleRouteHandler(
|
|
11
|
-
() => import("@brightweblabs/module-crm"),
|
|
12
|
-
"handleCrmContactsPostRequest",
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
export const PATCH = createModuleRouteHandler(
|
|
16
|
-
() => import("@brightweblabs/module-crm"),
|
|
17
|
-
"handleCrmContactsPatchRequest",
|
|
18
|
-
);
|
|
1
|
+
export { handleCrmContactsGetRequest as GET } from "@brightweblabs/module-crm";
|
|
2
|
+
export { handleCrmContactsPatchRequest as PATCH } from "@brightweblabs/module-crm";
|
|
3
|
+
export { handleCrmContactsPostRequest as POST } from "@brightweblabs/module-crm";
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export const dynamic = "force-dynamic";
|
|
4
|
-
|
|
5
|
-
export const GET = createModuleRouteHandler(
|
|
6
|
-
() => import("@brightweblabs/module-crm"),
|
|
7
|
-
"handleCrmOrganizationsGetRequest",
|
|
8
|
-
);
|
|
1
|
+
export { handleCrmOrganizationsGetRequest as GET } from "@brightweblabs/module-crm";
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export const dynamic = "force-dynamic";
|
|
4
|
-
|
|
5
|
-
export const GET = createModuleRouteHandler(
|
|
6
|
-
() => import("@brightweblabs/module-crm"),
|
|
7
|
-
"handleCrmOwnersGetRequest",
|
|
8
|
-
);
|
|
1
|
+
export { handleCrmOwnersGetRequest as GET } from "@brightweblabs/module-crm";
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export const dynamic = "force-dynamic";
|
|
4
|
-
|
|
5
|
-
export const GET = createModuleRouteHandler(
|
|
6
|
-
() => import("@brightweblabs/module-crm"),
|
|
7
|
-
"handleCrmStatsGetRequest",
|
|
8
|
-
);
|
|
1
|
+
export { handleCrmStatsGetRequest as GET } from "@brightweblabs/module-crm";
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export const dynamic = "force-dynamic";
|
|
4
|
-
|
|
5
|
-
export const GET = createModuleRouteHandler(
|
|
6
|
-
() => import("@brightweblabs/module-crm"),
|
|
7
|
-
"handleCrmTimelineGetRequest",
|
|
8
|
-
);
|
|
1
|
+
export { handleCrmTimelineGetRequest as GET } from "@brightweblabs/module-crm";
|
|
@@ -1,25 +1,12 @@
|
|
|
1
1
|
# AGENTS.md
|
|
2
2
|
|
|
3
|
-
This
|
|
4
|
-
|
|
5
|
-
## Start here
|
|
6
|
-
|
|
7
|
-
- `README.md`: local setup commands and the starter surface list.
|
|
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
|
-
- `config/site.ts`: site name, description, and starter CTAs.
|
|
12
|
-
- `app/page.tsx`: starter landing page composition.
|
|
13
|
-
- `app/globals.css`: global design language and theme tokens.
|
|
3
|
+
This is a thin BrightWeb site shell. It intentionally ships no feature page or local component library.
|
|
14
4
|
|
|
15
5
|
## Working rules
|
|
16
6
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
## First validation pass
|
|
7
|
+
- Keep site identity in `config/site.ts` and theme values in `app/globals.css`.
|
|
8
|
+
- Add routes only as direct mounts of package-owned surfaces.
|
|
9
|
+
- Do not add demos, feature components, hooks, data access, or helper libraries to the scaffold layer.
|
|
10
|
+
- Build reusable site UI in a package, then mount its export here.
|
|
22
11
|
|
|
23
|
-
|
|
24
|
-
2. Open `/` and confirm the starter content renders correctly.
|
|
25
|
-
3. Check `config/site.ts`, `app/page.tsx`, and `app/globals.css` together before making large copy or layout changes.
|
|
12
|
+
Run the build after changing settings, theme files, or package mounts.
|
|
@@ -1,37 +1,10 @@
|
|
|
1
1
|
# Agent Guide
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This generated site contains settings, theme files, root layout wiring, and docs only. It has no default feature surface.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- `config/site.ts`: site identity settings.
|
|
6
|
+
- `app/globals.css`: site theme tokens and global styling.
|
|
7
|
+
- `app/layout.tsx`: root document wiring.
|
|
8
|
+
- `docs/ai/app-context.json`: machine-readable ownership summary.
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
This app is a normal Next.js App Router project with a local UI layer and light configuration.
|
|
10
|
-
|
|
11
|
-
- `app/`: route tree, layouts, and the starter landing page.
|
|
12
|
-
- `components/ui/`: local UI primitives used by the starter surface.
|
|
13
|
-
- `config/site.ts`: generated site identity, description, and CTA defaults.
|
|
14
|
-
- `lib/`: helper utilities such as class merging.
|
|
15
|
-
|
|
16
|
-
## Fast routing map
|
|
17
|
-
|
|
18
|
-
- `docs/ai/app-context.json`: machine-readable summary of this app's template, starter routes, and first-read files.
|
|
19
|
-
- `docs/ai/examples.md`: common setup and customization workflows.
|
|
20
|
-
- `README.md`: first-run setup steps.
|
|
21
|
-
- `config/site.ts`: site name, description, eyebrow, and starter CTA links.
|
|
22
|
-
- `app/page.tsx`: starter composition for the home page.
|
|
23
|
-
- `app/globals.css`: theme tokens, layout defaults, and base typography.
|
|
24
|
-
- `components/ui/*`: local component primitives used by the starter.
|
|
25
|
-
|
|
26
|
-
## Editing strategy
|
|
27
|
-
|
|
28
|
-
- Change `config/site.ts` first when the task is mostly copy or link updates.
|
|
29
|
-
- Change `app/page.tsx` first when the task is about page structure or section flow.
|
|
30
|
-
- Change `app/globals.css` and `components/ui/*` when the task affects the visual system.
|
|
31
|
-
- Keep changes local to this app unless the task explicitly requires a shared BrightWeb package.
|
|
32
|
-
|
|
33
|
-
## Validation checklist
|
|
34
|
-
|
|
35
|
-
1. Run the app locally.
|
|
36
|
-
2. Validate `/` on desktop and mobile sizes.
|
|
37
|
-
3. If you changed the visual system, check both `app/globals.css` and the affected `components/ui/*` files.
|
|
10
|
+
Create UI in a reusable package and add only a direct package re-export under `app/`.
|
|
@@ -1,35 +1,13 @@
|
|
|
1
1
|
# Agent Examples
|
|
2
2
|
|
|
3
|
-
Use these workflows after reading `AGENTS.md`, `docs/ai/README.md`, and `docs/ai/app-context.json`.
|
|
4
|
-
|
|
5
|
-
## First local setup
|
|
6
|
-
|
|
7
|
-
Goal: get the generated site starter running and ready for edits.
|
|
8
|
-
|
|
9
|
-
- Run the local dev server for this app or workspace.
|
|
10
|
-
- Open `/` and confirm the starter renders correctly.
|
|
11
|
-
- Review `config/site.ts`, `app/page.tsx`, and `app/globals.css` before making large changes.
|
|
12
|
-
|
|
13
3
|
## Change site identity
|
|
14
4
|
|
|
15
|
-
Goal: update the starter name, description, and CTA links.
|
|
16
|
-
|
|
17
5
|
- Edit `config/site.ts`.
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
## Restyle the starter
|
|
22
|
-
|
|
23
|
-
Goal: change the visual language without rewriting everything at once.
|
|
24
|
-
|
|
25
|
-
- Start in `app/globals.css` for colors, spacing, and typography direction.
|
|
26
|
-
- Update `components/ui/*` if shared primitives need to change.
|
|
27
|
-
- Validate `/` on both desktop and mobile sizes.
|
|
28
|
-
|
|
29
|
-
## Replace the starter sections
|
|
6
|
+
- Adjust theme tokens in `app/globals.css` if needed.
|
|
7
|
+
- Run the build.
|
|
30
8
|
|
|
31
|
-
|
|
9
|
+
## Mount a site surface
|
|
32
10
|
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
11
|
+
- Export the complete surface from a package.
|
|
12
|
+
- Add `app/page.tsx` as a direct package re-export.
|
|
13
|
+
- Keep feature code and reusable components out of the app scaffold.
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import Link from "next/link";
|
|
2
|
-
import { getStarterBootstrapChecklist } from "../../config/bootstrap";
|
|
3
|
-
|
|
4
|
-
export default function BootstrapPage() {
|
|
5
|
-
const checklist = getStarterBootstrapChecklist();
|
|
6
|
-
|
|
7
|
-
return (
|
|
8
|
-
<main className="shell">
|
|
9
|
-
<div className="frame">
|
|
10
|
-
<section className="hero">
|
|
11
|
-
<span className="eyebrow">Client Bootstrap</span>
|
|
12
|
-
<h1 className="title">Launch checklist for {checklist.client.brand.companyName}</h1>
|
|
13
|
-
<p className="lead">
|
|
14
|
-
This page turns the starter config into an operational checklist for provisioning a new client instance.
|
|
15
|
-
</p>
|
|
16
|
-
<div className="actions">
|
|
17
|
-
<Link href="/" className="action">Back to overview</Link>
|
|
18
|
-
<Link href="/playground/auth" className="action secondary">Open playgrounds</Link>
|
|
19
|
-
</div>
|
|
20
|
-
</section>
|
|
21
|
-
|
|
22
|
-
<section className="panel">
|
|
23
|
-
<div className="panel-inner">
|
|
24
|
-
<h2>Client summary</h2>
|
|
25
|
-
<div className="grid">
|
|
26
|
-
<article className="panel" style={{ background: "rgba(255,255,255,0.72)" }}>
|
|
27
|
-
<div className="panel-inner">
|
|
28
|
-
<p className="status ok">{checklist.client.brand.slug}</p>
|
|
29
|
-
<h3>{checklist.client.brand.productName}</h3>
|
|
30
|
-
<p className="muted">{checklist.client.brand.tagline}</p>
|
|
31
|
-
</div>
|
|
32
|
-
</article>
|
|
33
|
-
<article className="panel" style={{ background: "rgba(255,255,255,0.72)" }}>
|
|
34
|
-
<div className="panel-inner">
|
|
35
|
-
<p className={`status ${checklist.client.envReadiness.allReady ? "ok" : "warn"}`}>
|
|
36
|
-
{checklist.client.envReadiness.allReady ? "Ready" : "Blocked"}
|
|
37
|
-
</p>
|
|
38
|
-
<h3>Environment status</h3>
|
|
39
|
-
<p className="muted">
|
|
40
|
-
{checklist.client.envReadiness.allReady
|
|
41
|
-
? "All required environment keys are configured."
|
|
42
|
-
: `${checklist.client.envReadiness.missing.length} required key(s) still missing.`}
|
|
43
|
-
</p>
|
|
44
|
-
</div>
|
|
45
|
-
</article>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
</section>
|
|
49
|
-
|
|
50
|
-
<section className="grid" style={{ marginTop: 18 }}>
|
|
51
|
-
{checklist.sections.map((section) => (
|
|
52
|
-
<article key={section.key} className="panel">
|
|
53
|
-
<div className="panel-inner">
|
|
54
|
-
<h2>{section.title}</h2>
|
|
55
|
-
<ul className="list">
|
|
56
|
-
{section.items.map((item) => (
|
|
57
|
-
<li key={item.label}>
|
|
58
|
-
<div className="check-row">
|
|
59
|
-
<span className={`check-dot ${item.done ? "done" : "pending"}`} aria-hidden="true" />
|
|
60
|
-
<div>
|
|
61
|
-
<strong>{item.label}</strong>
|
|
62
|
-
{item.detail ? <p className="muted inline-detail">{item.detail}</p> : null}
|
|
63
|
-
</div>
|
|
64
|
-
</div>
|
|
65
|
-
</li>
|
|
66
|
-
))}
|
|
67
|
-
</ul>
|
|
68
|
-
</div>
|
|
69
|
-
</article>
|
|
70
|
-
))}
|
|
71
|
-
</section>
|
|
72
|
-
</div>
|
|
73
|
-
</main>
|
|
74
|
-
);
|
|
75
|
-
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import Link from "next/link";
|
|
2
|
-
import { getStarterClientConfig } from "../config/client";
|
|
3
|
-
|
|
4
|
-
export default function HomePage() {
|
|
5
|
-
const config = getStarterClientConfig();
|
|
6
|
-
|
|
7
|
-
return (
|
|
8
|
-
<main className="shell starter-home">
|
|
9
|
-
<div className="frame">
|
|
10
|
-
<section className="starter-hero">
|
|
11
|
-
<div className="starter-hero-copy">
|
|
12
|
-
<span className="eyebrow">{config.brand.companyName}</span>
|
|
13
|
-
<h1 className="title">{config.brand.productName}</h1>
|
|
14
|
-
<p className="lead">{config.brand.tagline}</p>
|
|
15
|
-
<div className="actions">
|
|
16
|
-
<Link href="/preview/app-shell" className="action">Preview App Shell</Link>
|
|
17
|
-
<Link href="/bootstrap" className="action secondary">Open Bootstrap Checklist</Link>
|
|
18
|
-
<Link href="/playground/auth" className="action secondary">Open Module Playgrounds</Link>
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
|
|
22
|
-
<div className="starter-hero-card panel">
|
|
23
|
-
<div className="panel-inner">
|
|
24
|
-
<p className={`status ${config.envReadiness.allReady ? "ok" : "warn"}`}>
|
|
25
|
-
{config.envReadiness.allReady ? "Starter ready" : "Setup in progress"}
|
|
26
|
-
</p>
|
|
27
|
-
<div className="starter-stat-grid">
|
|
28
|
-
<div>
|
|
29
|
-
<span className="stat-number">{config.enabledModules.length}</span>
|
|
30
|
-
<p className="muted">enabled modules</p>
|
|
31
|
-
</div>
|
|
32
|
-
<div>
|
|
33
|
-
<span className="stat-number">{config.envStatus.filter((item) => item.present).length}</span>
|
|
34
|
-
<p className="muted">configured env keys</p>
|
|
35
|
-
</div>
|
|
36
|
-
</div>
|
|
37
|
-
<div className="starter-hero-note">
|
|
38
|
-
<strong>What this template gives you</strong>
|
|
39
|
-
<p className="muted">
|
|
40
|
-
One place to brand, provision, preview, and validate a new client before the first deployment.
|
|
41
|
-
</p>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
</div>
|
|
45
|
-
</section>
|
|
46
|
-
|
|
47
|
-
<section className="grid starter-signal-grid">
|
|
48
|
-
<article className="panel preview-glass-card">
|
|
49
|
-
<div className="panel-inner">
|
|
50
|
-
<p className="eyebrow">Brand</p>
|
|
51
|
-
<h2>{config.brand.companyName}</h2>
|
|
52
|
-
<p className="muted">{config.brand.contactEmail} · {config.brand.supportEmail}</p>
|
|
53
|
-
<p className="package-name">{config.brand.slug}</p>
|
|
54
|
-
</div>
|
|
55
|
-
</article>
|
|
56
|
-
|
|
57
|
-
<article className="panel preview-glass-card">
|
|
58
|
-
<div className="panel-inner">
|
|
59
|
-
<p className="eyebrow">Infrastructure</p>
|
|
60
|
-
<h2>{config.envReadiness.allReady ? "Ready to validate" : "Needs provisioning"}</h2>
|
|
61
|
-
<p className="muted">
|
|
62
|
-
{config.envReadiness.allReady
|
|
63
|
-
? "Core env and service wiring are present."
|
|
64
|
-
: `${config.envReadiness.missing.length} required environment key(s) are still missing.`}
|
|
65
|
-
</p>
|
|
66
|
-
</div>
|
|
67
|
-
</article>
|
|
68
|
-
</section>
|
|
69
|
-
|
|
70
|
-
<section className="panel" style={{ marginTop: 18 }}>
|
|
71
|
-
<div className="panel-inner">
|
|
72
|
-
<h2>Enabled platform modules</h2>
|
|
73
|
-
<div className="grid">
|
|
74
|
-
{config.enabledModules.map((moduleConfig) => (
|
|
75
|
-
<article key={moduleConfig.key} className="panel preview-glass-card" style={{ background: "rgba(255,255,255,0.72)" }}>
|
|
76
|
-
<div className="panel-inner">
|
|
77
|
-
<p className={`status ${moduleConfig.enabled ? "ok" : "warn"}`}>{moduleConfig.placement}</p>
|
|
78
|
-
<h3>{moduleConfig.label}</h3>
|
|
79
|
-
<p className="muted">{moduleConfig.description}</p>
|
|
80
|
-
<p className="package-name">{moduleConfig.packageName}</p>
|
|
81
|
-
{moduleConfig.playgroundHref ? (
|
|
82
|
-
<Link href={moduleConfig.playgroundHref} className="inline-link">
|
|
83
|
-
Open module playground
|
|
84
|
-
</Link>
|
|
85
|
-
) : null}
|
|
86
|
-
</div>
|
|
87
|
-
</article>
|
|
88
|
-
))}
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
</section>
|
|
92
|
-
|
|
93
|
-
<section className="grid" style={{ marginTop: 18 }}>
|
|
94
|
-
<article className="panel preview-glass-card">
|
|
95
|
-
<div className="panel-inner">
|
|
96
|
-
<h2>App-shell surfaces</h2>
|
|
97
|
-
<ul className="list">
|
|
98
|
-
{config.shellPreview.primaryNav.map((item) => (
|
|
99
|
-
<li key={item.href}>{item.label} · {item.href}</li>
|
|
100
|
-
))}
|
|
101
|
-
{config.shellPreview.moduleGroups.map((group) => (
|
|
102
|
-
<li key={group.key}>
|
|
103
|
-
{group.label} · {group.children.length} item(s)
|
|
104
|
-
</li>
|
|
105
|
-
))}
|
|
106
|
-
{config.shellPreview.adminNavItem ? <li>{config.shellPreview.adminNavItem.label} · {config.shellPreview.adminNavItem.href}</li> : null}
|
|
107
|
-
</ul>
|
|
108
|
-
</div>
|
|
109
|
-
</article>
|
|
110
|
-
|
|
111
|
-
<article className="panel preview-glass-card">
|
|
112
|
-
<div className="panel-inner">
|
|
113
|
-
<h2>Starter controls</h2>
|
|
114
|
-
<ul className="list">
|
|
115
|
-
<li>`config/brand.ts` for client identity and contact details.</li>
|
|
116
|
-
<li>`app/globals.css` for color and theme token management.</li>
|
|
117
|
-
<li>`config/modules.ts` for enabled platform modules.</li>
|
|
118
|
-
<li>`config/env.ts` for infra requirements and readiness checks.</li>
|
|
119
|
-
<li>`.env.local` for per-client service credentials and local runtime overrides.</li>
|
|
120
|
-
</ul>
|
|
121
|
-
</div>
|
|
122
|
-
</article>
|
|
123
|
-
</section>
|
|
124
|
-
|
|
125
|
-
<section className="panel" style={{ marginTop: 18 }}>
|
|
126
|
-
<div className="panel-inner">
|
|
127
|
-
<h2>Infrastructure checklist</h2>
|
|
128
|
-
<div className="grid">
|
|
129
|
-
{config.envStatus.map((item) => (
|
|
130
|
-
<article key={item.key} className="panel preview-glass-card" style={{ background: "rgba(255,255,255,0.72)" }}>
|
|
131
|
-
<div className="panel-inner">
|
|
132
|
-
<p className={`status ${item.present ? "ok" : "warn"}`}>{item.present ? "Configured" : "Missing"}</p>
|
|
133
|
-
<h3>{item.key}</h3>
|
|
134
|
-
<p className="muted">{item.description}</p>
|
|
135
|
-
<p className="package-name">{item.scope} · {item.requiredFor.join(", ")}</p>
|
|
136
|
-
</div>
|
|
137
|
-
</article>
|
|
138
|
-
))}
|
|
139
|
-
</div>
|
|
140
|
-
</div>
|
|
141
|
-
</section>
|
|
142
|
-
</div>
|
|
143
|
-
</main>
|
|
144
|
-
);
|
|
145
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
import Link from "next/link";
|
|
3
|
-
import { getEnabledStarterModules } from "../../config/modules";
|
|
4
|
-
|
|
5
|
-
const links = getEnabledStarterModules()
|
|
6
|
-
.filter((moduleConfig) => moduleConfig.playgroundHref)
|
|
7
|
-
.map((moduleConfig) => ({
|
|
8
|
-
href: moduleConfig.playgroundHref!,
|
|
9
|
-
label: moduleConfig.label,
|
|
10
|
-
}));
|
|
11
|
-
|
|
12
|
-
export default function PlaygroundLayout({ children }: { children: ReactNode }) {
|
|
13
|
-
return (
|
|
14
|
-
<main className="shell">
|
|
15
|
-
<div className="frame playground-layout">
|
|
16
|
-
<aside className="panel sidebar">
|
|
17
|
-
<div className="panel-inner stack">
|
|
18
|
-
<div>
|
|
19
|
-
<span className="eyebrow">Sandbox</span>
|
|
20
|
-
<h2 style={{ marginBottom: 8 }}>Module Playground</h2>
|
|
21
|
-
<p className="muted">
|
|
22
|
-
Use these routes to inspect package behavior while editing the shared repo.
|
|
23
|
-
</p>
|
|
24
|
-
</div>
|
|
25
|
-
<nav className="nav-list">
|
|
26
|
-
{links.map((link) => (
|
|
27
|
-
<Link key={link.href} href={link.href} className="nav-item">
|
|
28
|
-
{link.label}
|
|
29
|
-
</Link>
|
|
30
|
-
))}
|
|
31
|
-
<Link href="/" className="nav-item">
|
|
32
|
-
Back to overview
|
|
33
|
-
</Link>
|
|
34
|
-
</nav>
|
|
35
|
-
</div>
|
|
36
|
-
</aside>
|
|
37
|
-
<section className="stack">{children}</section>
|
|
38
|
-
</div>
|
|
39
|
-
</main>
|
|
40
|
-
);
|
|
41
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { AppShellPreview } from "../../../components/app-shell-preview";
|
|
2
|
-
|
|
3
|
-
export default function AppShellPreviewPage() {
|
|
4
|
-
return (
|
|
5
|
-
<main className="shell shell-preview-page">
|
|
6
|
-
<div className="frame">
|
|
7
|
-
<AppShellPreview />
|
|
8
|
-
</div>
|
|
9
|
-
</main>
|
|
10
|
-
);
|
|
11
|
-
}
|