@clubedge/create-clubedge-app 0.1.13 → 0.2.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  All notable changes to `create-clubedge-app` are documented here.
4
4
 
5
+ ## 0.2.1
6
+
7
+ - Publish the default Starter pin in the `clubedge` field of `package.json`. The CLI and release workflow read it from there, and the npm registry exposes it so the website always shows the Starter each CLI version scaffolds.
8
+ - Optionally trigger a website rebuild after a release when the `SITE_DEPLOY_HOOK` secret is configured.
9
+
10
+ ## 0.2.0
11
+
12
+ - Default to Starter `v0.2.0`, which adds project identity in `site.json`, dashboard protection, rate-limited sign-in and sign-up, and lazy environment validation.
13
+ - Write the project name to `apps/web/src/config/site.json` when the Starter provides it, instead of replacing strings in source files. Starter `v0.1.x` refs keep the previous behavior.
14
+
5
15
  ## 0.1.13
6
16
 
7
17
  ## 0.1.12
package/README.md CHANGED
@@ -12,23 +12,23 @@ The CLI downloads a tested Starter release, names the generated project, creates
12
12
  Each CLI release is tested against one specific Starter release:
13
13
 
14
14
  ```text
15
- create-clubedge-app v0.1.13
15
+ create-clubedge-app v0.2.1
16
16
  |
17
17
  v
18
- Clubedge Starter v0.1.1
19
- commit 0be0c18d41f01cd011c576fb65c25711081b8ad4
18
+ Clubedge Starter v0.2.0
19
+ commit db15901da90d8d8a190d158c895dfe76c172b415
20
20
  ```
21
21
 
22
22
  The current relationship is:
23
23
 
24
24
  | CLI release | Default Starter release | Meaning |
25
25
  | --- | --- | --- |
26
- | `create-clubedge-app@0.1.13` | `clubedge-starter@v0.1.1` | The CLI's required, tested default |
26
+ | `create-clubedge-app@0.2.1` | `clubedge-starter@v0.2.0` | The CLI's required, tested default |
27
27
 
28
28
  This means the same CLI version always scaffolds the same Starter revision by default. The CLI does not silently follow Starter `main`.
29
29
 
30
- The `v0.1.1` tag is expected to resolve to commit
31
- `0be0c18d41f01cd011c576fb65c25711081b8ad4`. The CLI verifies this before
30
+ The `v0.2.0` tag is expected to resolve to commit
31
+ `db15901da90d8d8a190d158c895dfe76c172b415`. The CLI verifies this before
32
32
  scaffolding with the default reference and fails rather than silently using a
33
33
  moved tag.
34
34
 
@@ -73,7 +73,7 @@ pnpm dlx @clubedge/create-clubedge-app
73
73
  ```text
74
74
  Usage: pnpm dlx @clubedge/create-clubedge-app [project-directory] [options]
75
75
 
76
- --ref <ref> Select a starter tag, branch, or commit (default: v0.1.1)
76
+ --ref <ref> Select a starter tag, branch, or commit (default: v0.2.0)
77
77
  --no-install Skip pnpm install
78
78
  --no-git Skip Git initialization
79
79
  -h, --help Show help
@@ -87,9 +87,9 @@ pnpm dlx @clubedge/create-clubedge-app my-app --ref <starter-tag-or-commit>
87
87
  pnpm dlx @clubedge/create-clubedge-app my-app --no-install
88
88
  ```
89
89
 
90
- The target directory must be empty or not exist. The CLI will not delete or overwrite files in a non-empty target directory. The default is the tested `v0.1.1` Starter release, so the same CLI version produces the same Starter revision. Use `--ref` to explicitly select a tag, branch, or commit.
90
+ The target directory must be empty or not exist. The CLI will not delete or overwrite files in a non-empty target directory. The default is the tested `v0.2.0` Starter release, so the same CLI version produces the same Starter revision. Use `--ref` to explicitly select a tag, branch, or commit.
91
91
 
92
- The default is the tested Starter release tag `v0.1.1`. Every generated project records its CLI version, Starter repository, exact Starter ref, and resolved Starter commit in `package.json` and `README.md`.
92
+ The default is the tested Starter release tag `v0.2.0`. Every generated project records its CLI version, Starter repository, exact Starter ref, and resolved Starter commit in `package.json` and `README.md`.
93
93
 
94
94
  Use `--ref` only when you intentionally want a different Starter revision:
95
95
 
@@ -101,7 +101,7 @@ pnpm dlx @clubedge/create-clubedge-app my-app
101
101
  pnpm dlx @clubedge/create-clubedge-app my-app --ref main
102
102
 
103
103
  # Reproduce a specific Starter release or commit
104
- pnpm dlx @clubedge/create-clubedge-app my-app --ref v0.1.1
104
+ pnpm dlx @clubedge/create-clubedge-app my-app --ref v0.2.0
105
105
  pnpm dlx @clubedge/create-clubedge-app my-app --ref <commit-sha>
106
106
  ```
107
107
 
package/bin/create.mjs CHANGED
@@ -2,20 +2,23 @@
2
2
 
3
3
  import { cancel, intro, isCancel, outro, spinner, text } from "@clack/prompts";
4
4
  import { downloadTemplate } from "giget";
5
- import { cp, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
5
+ import { access, cp, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
6
6
  import { spawn } from "node:child_process";
7
7
  import { basename, dirname, join, resolve } from "node:path";
8
8
  import process from "node:process";
9
9
  import { pathToFileURL } from "node:url";
10
10
 
11
- const starterRepository = "Clubedge/clubedge-starter";
12
- const defaultStarterRef = "v0.1.1";
13
- const defaultStarterCommit = "0be0c18d41f01cd011c576fb65c25711081b8ad4";
11
+ // package.json is the single source for the version and the tested Starter pin. It is
12
+ // published with the package, so the npm registry exposes exactly what each release scaffolds.
13
+ const packageManifest = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8"));
14
+ const packageVersion = packageManifest.version;
15
+ const {
16
+ starterRepository,
17
+ starterRef: defaultStarterRef,
18
+ starterCommit: defaultStarterCommit,
19
+ } = packageManifest.clubedge;
14
20
  const siteUrl = "https://clubedge.live";
15
21
  const cliUrl = "https://starter.clubedge.live";
16
- const packageVersion = JSON.parse(
17
- await readFile(new URL("../package.json", import.meta.url), "utf8"),
18
- ).version;
19
22
 
20
23
  /* ------------------------------------------------------------------ */
21
24
  /* Branding: big block-letter banner */
@@ -263,6 +266,63 @@ async function ensureTargetIsSafe(directory) {
263
266
  }
264
267
  }
265
268
 
269
+ async function fileExists(path) {
270
+ try {
271
+ await access(path);
272
+ return true;
273
+ } catch {
274
+ return false;
275
+ }
276
+ }
277
+
278
+ /** Starter v0.2+ keeps project identity in apps/web/src/config/site.json. */
279
+ async function customizeSiteConfig(siteConfigPath, packageName, displayName) {
280
+ const siteConfig = JSON.parse(await readFile(siteConfigPath, "utf8"));
281
+ siteConfig.name = displayName;
282
+ siteConfig.shortName = displayName;
283
+ siteConfig.description = `${displayName} application foundation.`;
284
+ siteConfig.serviceId = packageName;
285
+ siteConfig.workspaceLabel = "Application workspace";
286
+ await writeFile(siteConfigPath, `${JSON.stringify(siteConfig, null, 2)}\n`);
287
+ }
288
+
289
+ /** Starter v0.1.x has no site.json, so names are replaced in known source files. */
290
+ async function customizeLegacySources(directory, displayName) {
291
+ const layoutPath = join(directory, "apps", "web", "src", "app", "layout.tsx");
292
+ const layout = await readFile(layoutPath, "utf8");
293
+ const customizedLayout = layout
294
+ .replaceAll('"Clubedge Starter"', JSON.stringify(displayName))
295
+ .replace(`%s \u00b7 Clubedge Starter`, `%s \u00b7 ${displayName}`)
296
+ .replace(
297
+ "A production-minded foundation for Clubedge applications.",
298
+ `${displayName} application foundation.`,
299
+ );
300
+ await writeFile(layoutPath, customizedLayout);
301
+
302
+ const appFiles = [
303
+ join(directory, "apps", "web", "src", "app", "page.tsx"),
304
+ join(directory, "apps", "web", "src", "app", "dashboard", "_components", "app-sidebar.tsx"),
305
+ join(directory, "apps", "web", "src", "app", "dashboard", "page.tsx"),
306
+ join(directory, "apps", "web", "src", "app", "login", "page.tsx"),
307
+ ];
308
+ for (const appFile of appFiles) {
309
+ let source;
310
+ try {
311
+ source = await readFile(appFile, "utf8");
312
+ } catch (error) {
313
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
314
+ continue;
315
+ }
316
+ throw error;
317
+ }
318
+ const customizedSource = source
319
+ .replaceAll("Clubedge Starter", displayName)
320
+ .replaceAll('>Clubedge<', `>${displayName}<`)
321
+ .replaceAll("Starter workspace", "Application workspace");
322
+ await writeFile(appFile, customizedSource);
323
+ }
324
+ }
325
+
266
326
  async function customizeProject(
267
327
  directory,
268
328
  packageName,
@@ -301,38 +361,11 @@ async function customizeProject(
301
361
  );
302
362
  await writeFile(readmePath, customizedReadme);
303
363
 
304
- const layoutPath = join(directory, "apps", "web", "src", "app", "layout.tsx");
305
- const layout = await readFile(layoutPath, "utf8");
306
- const customizedLayout = layout
307
- .replaceAll('"Clubedge Starter"', JSON.stringify(displayName))
308
- .replace(`%s \u00b7 Clubedge Starter`, `%s \u00b7 ${displayName}`)
309
- .replace(
310
- "A production-minded foundation for Clubedge applications.",
311
- `${displayName} application foundation.`,
312
- );
313
- await writeFile(layoutPath, customizedLayout);
314
-
315
- const appFiles = [
316
- join(directory, "apps", "web", "src", "app", "page.tsx"),
317
- join(directory, "apps", "web", "src", "app", "dashboard", "_components", "app-sidebar.tsx"),
318
- join(directory, "apps", "web", "src", "app", "dashboard", "page.tsx"),
319
- join(directory, "apps", "web", "src", "app", "login", "page.tsx"),
320
- ];
321
- for (const appFile of appFiles) {
322
- let source;
323
- try {
324
- source = await readFile(appFile, "utf8");
325
- } catch (error) {
326
- if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
327
- continue;
328
- }
329
- throw error;
330
- }
331
- const customizedSource = source
332
- .replaceAll("Clubedge Starter", displayName)
333
- .replaceAll('>Clubedge<', `>${displayName}<`)
334
- .replaceAll("Starter workspace", "Application workspace");
335
- await writeFile(appFile, customizedSource);
364
+ const siteConfigPath = join(directory, "apps", "web", "src", "config", "site.json");
365
+ if (await fileExists(siteConfigPath)) {
366
+ await customizeSiteConfig(siteConfigPath, packageName, displayName);
367
+ } else {
368
+ await customizeLegacySources(directory, displayName);
336
369
  }
337
370
 
338
371
  const exampleEnvironment = join(directory, ".env.example");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clubedge/create-clubedge-app",
3
- "version": "0.1.13",
3
+ "version": "0.2.1",
4
4
  "description": "Create a Next.js application from the Clubedge Starter reference implementation.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.9.0",
@@ -17,6 +17,11 @@
17
17
  "engines": {
18
18
  "node": ">=22.12.0"
19
19
  },
20
+ "clubedge": {
21
+ "starterRepository": "Clubedge/clubedge-starter",
22
+ "starterRef": "v0.2.0",
23
+ "starterCommit": "db15901da90d8d8a190d158c895dfe76c172b415"
24
+ },
20
25
  "license": "Apache-2.0",
21
26
  "repository": {
22
27
  "type": "git",