@jxsuite/starters 2.0.1 → 3.0.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.
Files changed (33) hide show
  1. package/README.md +2 -2
  2. package/index.ts +17 -24
  3. package/package.json +7 -4
  4. package/sites/blog/document.schema.json +52 -26
  5. package/sites/blog/package.json +3 -3
  6. package/sites/course/document.schema.json +52 -26
  7. package/sites/course/package.json +3 -3
  8. package/sites/course/pages/enroll.md +4 -4
  9. package/sites/course/pages/index.md +3 -3
  10. package/sites/event/document.schema.json +52 -26
  11. package/sites/event/package.json +3 -3
  12. package/sites/event/pages/speakers.md +8 -0
  13. package/sites/fitness-studio/document.schema.json +52 -26
  14. package/sites/fitness-studio/package.json +3 -3
  15. package/sites/home-services/document.schema.json +52 -26
  16. package/sites/home-services/package.json +3 -3
  17. package/sites/home-services/pages/index.md +1 -0
  18. package/sites/museum/document.schema.json +52 -26
  19. package/sites/museum/package.json +3 -3
  20. package/sites/nonprofit/document.schema.json +52 -26
  21. package/sites/nonprofit/package.json +3 -3
  22. package/sites/portfolio/document.schema.json +52 -26
  23. package/sites/portfolio/package.json +3 -3
  24. package/sites/professional-firm/document.schema.json +52 -26
  25. package/sites/professional-firm/package.json +3 -3
  26. package/sites/real-estate/document.schema.json +52 -26
  27. package/sites/real-estate/package.json +3 -3
  28. package/sites/restaurant/document.schema.json +52 -26
  29. package/sites/restaurant/package.json +3 -3
  30. package/sites/saas/document.schema.json +52 -26
  31. package/sites/saas/package.json +3 -3
  32. package/sites/shop/document.schema.json +52 -26
  33. package/sites/shop/package.json +3 -3
package/README.md CHANGED
@@ -67,7 +67,7 @@ bun create @jxsuite my-site --template restaurant
67
67
  - **`package.json` is rebuilt from scratch** with current dependency ranges, so a clone never inherits whatever the in-repo starter pinned.
68
68
  - `--template` resolves built-in template ids first, then registry starter ids; an unknown id falls back to `blank`.
69
69
 
70
- Two other consumers read the registry live: the dev server exposes it to Studio's picker at `GET /__studio/starters`, returning `listStarters()` verbatim (specs/server.md §4.1), and the desktop app imports `listStarters` directly in both its Electrobun and Chromium window layers.
70
+ Two other consumers read the registry live: the dev server exposes it to Studio's picker at `GET /__studio/starters`, returning `listStarters()` verbatim (specs/server.md §4.1), and the desktop app imports `listStarters` directly in its Chromium window layer and its Electron hub.
71
71
 
72
72
  ## Authoring or modifying a starter
73
73
 
@@ -95,7 +95,7 @@ Adding a starter needs **no** desktop config change: `packages/desktop/scripts/v
95
95
 
96
96
  **Do not hand-edit the `@jxsuite/*` ranges in `sites/*/package.json`.** release-please rewrites them inside its release commit via `extra-files`; the gate is `bun run templates:check` (`templates:sync` to repair).
97
97
 
98
- **Packaged-desktop path contract.** ElectroBun inlines the bun-side JS graph, so `import.meta.dirname` resolves to `app/bun/` at runtime. `registry.json` and `sites/` must therefore be staged to `bun/registry.json` and `bun/sites` by `build.copy` in `packages/desktop/electrobun.config.ts` (specs/desktop.md §7.4).
98
+ **Packaged-desktop path contract.** The packaged application's Bun backend is a single bundle, so `import.meta.dirname` no longer resolves to this package. `registry.json` and `sites/` are staged beside the bundle (`BACKEND_DATA` in `packages/desktop/scripts/lib/backend-bundle.ts`), and `bun run smoke` in `packages/desktop` fails if the staged copy cannot list the starters (specs/desktop.md §7).
99
99
 
100
100
  **The screenshot lane ignores this package's source.** It watches only `registry.json` and the six starter roots a shot actually opens (`.github/workflows/screenshots.yml`); a registry change arms exactly one shot, `new-project`, because that modal's gallery _is_ `listStarters()`.
101
101
 
package/index.ts CHANGED
@@ -11,38 +11,31 @@
11
11
  import { readFileSync } from "node:fs";
12
12
  import { join } from "node:path";
13
13
 
14
- /** One entry in {@link registry.json} — everything the picker UI needs to render a template card. */
15
- export interface StarterMeta {
16
- /** Stable id; also the directory name under `sites/` and the value threaded as `starter`. */
17
- id: string;
18
- /** Human-facing display name, e.g. "Bistro & Café". */
19
- name: string;
20
- /** Industry archetype label, e.g. "Restaurant & Food". */
21
- industry: string;
22
- /** One-line summary shown under the name. */
23
- tagline: string;
24
- /** Longer description for the showcase / tooltip. */
25
- description: string;
26
- /** Short bullets naming the Jx features the starter demonstrates. */
27
- features: string[];
28
- /** Accent colour (hex) — mirrors the site's primary token; used for card theming. */
29
- accent: string;
30
- /** Small preview image as a self-contained `data:` URI so the picker needs no extra plumbing. */
31
- thumbnail: string;
32
- }
14
+ import type { StarterInfo } from "@jxsuite/protocol";
15
+
16
+ /**
17
+ * One entry in `registry.json`. The wire contract owns the declaration (`StarterInfo`); this
18
+ * package keeps exporting it under its published name so existing importers keep compiling.
19
+ */
20
+ export type { StarterInfo as StarterMeta } from "@jxsuite/protocol";
33
21
 
34
22
  const STARTERS_DIR = import.meta.dirname;
35
23
 
36
24
  /** Absolute path to the directory holding the per-starter project trees. */
37
25
  export const SITES_DIR = join(STARTERS_DIR, "sites");
38
26
 
39
- let _cache: StarterMeta[] | null = null;
27
+ let _cache: StarterInfo[] | null = null;
40
28
 
41
29
  /** Read and cache the starter registry. */
42
- export function listStarters(): StarterMeta[] {
30
+ export function listStarters(): StarterInfo[] {
43
31
  if (!_cache) {
44
32
  const raw = readFileSync(join(STARTERS_DIR, "registry.json"), "utf8");
45
- _cache = JSON.parse(raw) as StarterMeta[];
33
+ /*
34
+ * SAFETY: registry.json is a committed file shipped inside this package, never user input, and
35
+ * tests/registry.test.ts asserts that every entry carries each StarterInfo member as a non-empty
36
+ * string (features as a non-empty string array), so the parsed array matches StarterInfo[].
37
+ */
38
+ _cache = JSON.parse(raw) as StarterInfo[];
46
39
  }
47
40
  return _cache;
48
41
  }
@@ -51,9 +44,9 @@ export function listStarters(): StarterMeta[] {
51
44
  * Look up a single starter's metadata by id.
52
45
  *
53
46
  * @param {string} id
54
- * @returns {StarterMeta | undefined}
47
+ * @returns {StarterInfo | undefined}
55
48
  */
56
- export function getStarter(id: string): StarterMeta | undefined {
49
+ export function getStarter(id: string): StarterInfo | undefined {
57
50
  return listStarters().find((s) => s.id === id);
58
51
  }
59
52
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jxsuite/starters",
3
- "version": "2.0.1",
3
+ "version": "3.0.1",
4
4
  "description": "Starter site templates for new Jx projects",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -25,10 +25,13 @@
25
25
  "test": "bun test --isolate",
26
26
  "test:coverage": "bun test --isolate --coverage"
27
27
  },
28
+ "dependencies": {
29
+ "@jxsuite/protocol": "^4.0.0"
30
+ },
28
31
  "devDependencies": {
29
- "@jxsuite/parser": "^2.0.1",
30
- "@jxsuite/runtime": "^4.1.0",
31
- "@jxsuite/schema": "^3.0.0",
32
+ "@jxsuite/parser": "^4.0.1",
33
+ "@jxsuite/runtime": "^5.1.0",
34
+ "@jxsuite/schema": "^4.0.0",
32
35
  "ajv": "^8.20.0",
33
36
  "ajv-formats": "^3.0.1"
34
37
  }
@@ -14905,6 +14905,32 @@
14905
14905
  }
14906
14906
  ]
14907
14907
  },
14908
+ "fit-tolerance": {
14909
+ "oneOf": [
14910
+ {
14911
+ "type": "string"
14912
+ },
14913
+ {
14914
+ "type": "number"
14915
+ },
14916
+ {
14917
+ "$ref": "#/$defs/v1/$defs/RefObject"
14918
+ }
14919
+ ]
14920
+ },
14921
+ "fitTolerance": {
14922
+ "oneOf": [
14923
+ {
14924
+ "type": "string"
14925
+ },
14926
+ {
14927
+ "type": "number"
14928
+ },
14929
+ {
14930
+ "$ref": "#/$defs/v1/$defs/RefObject"
14931
+ }
14932
+ ]
14933
+ },
14908
14934
  "flex": {
14909
14935
  "oneOf": [
14910
14936
  {
@@ -15269,19 +15295,6 @@
15269
15295
  }
15270
15296
  ]
15271
15297
  },
15272
- "flow-tolerance": {
15273
- "oneOf": [
15274
- {
15275
- "type": "string"
15276
- },
15277
- {
15278
- "type": "number"
15279
- },
15280
- {
15281
- "$ref": "#/$defs/v1/$defs/RefObject"
15282
- }
15283
- ]
15284
- },
15285
15298
  "flowFrom": {
15286
15299
  "oneOf": [
15287
15300
  {
@@ -15308,19 +15321,6 @@
15308
15321
  }
15309
15322
  ]
15310
15323
  },
15311
- "flowTolerance": {
15312
- "oneOf": [
15313
- {
15314
- "type": "string"
15315
- },
15316
- {
15317
- "type": "number"
15318
- },
15319
- {
15320
- "$ref": "#/$defs/v1/$defs/RefObject"
15321
- }
15322
- ]
15323
- },
15324
15324
  "font": {
15325
15325
  "oneOf": [
15326
15326
  {
@@ -25279,6 +25279,19 @@
25279
25279
  }
25280
25280
  ]
25281
25281
  },
25282
+ "timeline-trigger-range": {
25283
+ "oneOf": [
25284
+ {
25285
+ "type": "string"
25286
+ },
25287
+ {
25288
+ "type": "number"
25289
+ },
25290
+ {
25291
+ "$ref": "#/$defs/v1/$defs/RefObject"
25292
+ }
25293
+ ]
25294
+ },
25282
25295
  "timeline-trigger-source": {
25283
25296
  "oneOf": [
25284
25297
  {
@@ -25409,6 +25422,19 @@
25409
25422
  }
25410
25423
  ]
25411
25424
  },
25425
+ "timelineTriggerRange": {
25426
+ "oneOf": [
25427
+ {
25428
+ "type": "string"
25429
+ },
25430
+ {
25431
+ "type": "number"
25432
+ },
25433
+ {
25434
+ "$ref": "#/$defs/v1/$defs/RefObject"
25435
+ }
25436
+ ]
25437
+ },
25412
25438
  "timelineTriggerSource": {
25413
25439
  "oneOf": [
25414
25440
  {
@@ -9,10 +9,10 @@
9
9
  "dev": "jx dev"
10
10
  },
11
11
  "dependencies": {
12
- "@jxsuite/parser": "^2.0.1"
12
+ "@jxsuite/parser": "^4.0.1"
13
13
  },
14
14
  "devDependencies": {
15
- "@jxsuite/compiler": "^5.1.2",
16
- "@jxsuite/runtime": "^4.1.0"
15
+ "@jxsuite/compiler": "^6.0.2",
16
+ "@jxsuite/runtime": "^5.1.0"
17
17
  }
18
18
  }
@@ -14905,6 +14905,32 @@
14905
14905
  }
14906
14906
  ]
14907
14907
  },
14908
+ "fit-tolerance": {
14909
+ "oneOf": [
14910
+ {
14911
+ "type": "string"
14912
+ },
14913
+ {
14914
+ "type": "number"
14915
+ },
14916
+ {
14917
+ "$ref": "#/$defs/v1/$defs/RefObject"
14918
+ }
14919
+ ]
14920
+ },
14921
+ "fitTolerance": {
14922
+ "oneOf": [
14923
+ {
14924
+ "type": "string"
14925
+ },
14926
+ {
14927
+ "type": "number"
14928
+ },
14929
+ {
14930
+ "$ref": "#/$defs/v1/$defs/RefObject"
14931
+ }
14932
+ ]
14933
+ },
14908
14934
  "flex": {
14909
14935
  "oneOf": [
14910
14936
  {
@@ -15269,19 +15295,6 @@
15269
15295
  }
15270
15296
  ]
15271
15297
  },
15272
- "flow-tolerance": {
15273
- "oneOf": [
15274
- {
15275
- "type": "string"
15276
- },
15277
- {
15278
- "type": "number"
15279
- },
15280
- {
15281
- "$ref": "#/$defs/v1/$defs/RefObject"
15282
- }
15283
- ]
15284
- },
15285
15298
  "flowFrom": {
15286
15299
  "oneOf": [
15287
15300
  {
@@ -15308,19 +15321,6 @@
15308
15321
  }
15309
15322
  ]
15310
15323
  },
15311
- "flowTolerance": {
15312
- "oneOf": [
15313
- {
15314
- "type": "string"
15315
- },
15316
- {
15317
- "type": "number"
15318
- },
15319
- {
15320
- "$ref": "#/$defs/v1/$defs/RefObject"
15321
- }
15322
- ]
15323
- },
15324
15324
  "font": {
15325
15325
  "oneOf": [
15326
15326
  {
@@ -25279,6 +25279,19 @@
25279
25279
  }
25280
25280
  ]
25281
25281
  },
25282
+ "timeline-trigger-range": {
25283
+ "oneOf": [
25284
+ {
25285
+ "type": "string"
25286
+ },
25287
+ {
25288
+ "type": "number"
25289
+ },
25290
+ {
25291
+ "$ref": "#/$defs/v1/$defs/RefObject"
25292
+ }
25293
+ ]
25294
+ },
25282
25295
  "timeline-trigger-source": {
25283
25296
  "oneOf": [
25284
25297
  {
@@ -25409,6 +25422,19 @@
25409
25422
  }
25410
25423
  ]
25411
25424
  },
25425
+ "timelineTriggerRange": {
25426
+ "oneOf": [
25427
+ {
25428
+ "type": "string"
25429
+ },
25430
+ {
25431
+ "type": "number"
25432
+ },
25433
+ {
25434
+ "$ref": "#/$defs/v1/$defs/RefObject"
25435
+ }
25436
+ ]
25437
+ },
25412
25438
  "timelineTriggerSource": {
25413
25439
  "oneOf": [
25414
25440
  {
@@ -9,10 +9,10 @@
9
9
  "dev": "jx dev"
10
10
  },
11
11
  "dependencies": {
12
- "@jxsuite/parser": "^2.0.1"
12
+ "@jxsuite/parser": "^4.0.1"
13
13
  },
14
14
  "devDependencies": {
15
- "@jxsuite/compiler": "^5.1.2",
16
- "@jxsuite/runtime": "^4.1.0"
15
+ "@jxsuite/compiler": "^6.0.2",
16
+ "@jxsuite/runtime": "^5.1.0"
17
17
  }
18
18
  }
@@ -19,7 +19,7 @@ Not sure if it's the right fit? Book a call with our admissions team and we'll w
19
19
  - **✓** Six monthly payment plans available
20
20
  - **✓** Need-based scholarships for eligible students
21
21
  - **✓** 7-day full refund, no questions asked
22
- :::
22
+ :::
23
23
 
24
24
  :::co-pricing{props.badge="Fall cohort · 24 seats" props.plan="Full Program" props.price="$8,900" props.period="or 6 monthly payments" props.description="14 weeks of live instruction, mentorship, and career support — end to end." props.cta="Apply Now" props.ctaHref="#apply" props.note="7-day full refund · scholarships available"}
25
25
 
@@ -28,9 +28,9 @@ Not sure if it's the right fit? Book a call with our admissions team and we'll w
28
28
  - Deployed full-stack capstone project
29
29
  - Career coaching & interview prep
30
30
  - Lifetime access to course materials
31
- :::
32
- ::::
33
- :::::
31
+ :::
32
+ ::::
33
+ :::::
34
34
 
35
35
  :::::section{id="apply" style.maxWidth="var(--max-width-narrow)" style.margin="0 auto" style.padding="clamp(3rem, 6vw, 4.5rem) 1.5rem"}
36
36
  ::co-section-header{props.eyebrow="apply" props.heading="Start your application" props.subheading="Tell us a little about yourself and admissions will be in touch within two business days."}
@@ -85,9 +85,9 @@ Your tuition covers 14 weeks of live instruction, one-on-one mentorship, and car
85
85
  - Deployed full-stack capstone project
86
86
  - Career coaching & interview prep
87
87
  - Lifetime access to course materials
88
- ::::
89
- :::::
90
- ::::::
88
+ ::::
89
+ :::::
90
+ ::::::
91
91
 
92
92
  :::::section{style.padding="clamp(3.5rem, 8vw, 6rem) 1.5rem" style.backgroundColor="var(--color-bg-cream)"}
93
93
  ::co-section-header{props.eyebrow="faq" props.heading="Questions, answered"}
@@ -14905,6 +14905,32 @@
14905
14905
  }
14906
14906
  ]
14907
14907
  },
14908
+ "fit-tolerance": {
14909
+ "oneOf": [
14910
+ {
14911
+ "type": "string"
14912
+ },
14913
+ {
14914
+ "type": "number"
14915
+ },
14916
+ {
14917
+ "$ref": "#/$defs/v1/$defs/RefObject"
14918
+ }
14919
+ ]
14920
+ },
14921
+ "fitTolerance": {
14922
+ "oneOf": [
14923
+ {
14924
+ "type": "string"
14925
+ },
14926
+ {
14927
+ "type": "number"
14928
+ },
14929
+ {
14930
+ "$ref": "#/$defs/v1/$defs/RefObject"
14931
+ }
14932
+ ]
14933
+ },
14908
14934
  "flex": {
14909
14935
  "oneOf": [
14910
14936
  {
@@ -15269,19 +15295,6 @@
15269
15295
  }
15270
15296
  ]
15271
15297
  },
15272
- "flow-tolerance": {
15273
- "oneOf": [
15274
- {
15275
- "type": "string"
15276
- },
15277
- {
15278
- "type": "number"
15279
- },
15280
- {
15281
- "$ref": "#/$defs/v1/$defs/RefObject"
15282
- }
15283
- ]
15284
- },
15285
15298
  "flowFrom": {
15286
15299
  "oneOf": [
15287
15300
  {
@@ -15308,19 +15321,6 @@
15308
15321
  }
15309
15322
  ]
15310
15323
  },
15311
- "flowTolerance": {
15312
- "oneOf": [
15313
- {
15314
- "type": "string"
15315
- },
15316
- {
15317
- "type": "number"
15318
- },
15319
- {
15320
- "$ref": "#/$defs/v1/$defs/RefObject"
15321
- }
15322
- ]
15323
- },
15324
15324
  "font": {
15325
15325
  "oneOf": [
15326
15326
  {
@@ -25279,6 +25279,19 @@
25279
25279
  }
25280
25280
  ]
25281
25281
  },
25282
+ "timeline-trigger-range": {
25283
+ "oneOf": [
25284
+ {
25285
+ "type": "string"
25286
+ },
25287
+ {
25288
+ "type": "number"
25289
+ },
25290
+ {
25291
+ "$ref": "#/$defs/v1/$defs/RefObject"
25292
+ }
25293
+ ]
25294
+ },
25282
25295
  "timeline-trigger-source": {
25283
25296
  "oneOf": [
25284
25297
  {
@@ -25409,6 +25422,19 @@
25409
25422
  }
25410
25423
  ]
25411
25424
  },
25425
+ "timelineTriggerRange": {
25426
+ "oneOf": [
25427
+ {
25428
+ "type": "string"
25429
+ },
25430
+ {
25431
+ "type": "number"
25432
+ },
25433
+ {
25434
+ "$ref": "#/$defs/v1/$defs/RefObject"
25435
+ }
25436
+ ]
25437
+ },
25412
25438
  "timelineTriggerSource": {
25413
25439
  "oneOf": [
25414
25440
  {
@@ -9,10 +9,10 @@
9
9
  "dev": "jx dev"
10
10
  },
11
11
  "dependencies": {
12
- "@jxsuite/parser": "^2.0.1"
12
+ "@jxsuite/parser": "^4.0.1"
13
13
  },
14
14
  "devDependencies": {
15
- "@jxsuite/compiler": "^5.1.2",
16
- "@jxsuite/runtime": "^4.1.0"
15
+ "@jxsuite/compiler": "^6.0.2",
16
+ "@jxsuite/runtime": "^5.1.0"
17
17
  }
18
18
  }
@@ -29,6 +29,7 @@ title: "Speakers — Horizon Conf 2026"
29
29
  :::div{style.fontFamily="var(--font-heading)" style.fontWeight="700" style.fontSize="1.05rem"}
30
30
  Jonas Berg
31
31
  :::
32
+
32
33
  :::div{style.fontSize="0.9rem" style.color="var(--color-text-muted)"}
33
34
  Infra Lead, Kestrel
34
35
  :::
@@ -38,6 +39,7 @@ Infra Lead, Kestrel
38
39
  :::div{style.fontFamily="var(--font-heading)" style.fontWeight="700" style.fontSize="1.05rem"}
39
40
  Sam Whitfield
40
41
  :::
42
+
41
43
  :::div{style.fontSize="0.9rem" style.color="var(--color-text-muted)"}
42
44
  Product Engineer, Ridgeline
43
45
  :::
@@ -47,6 +49,7 @@ Product Engineer, Ridgeline
47
49
  :::div{style.fontFamily="var(--font-heading)" style.fontWeight="700" style.fontSize="1.05rem"}
48
50
  Nadia Hassan
49
51
  :::
52
+
50
53
  :::div{style.fontSize="0.9rem" style.color="var(--color-text-muted)"}
51
54
  Design Systems, Cobalt
52
55
  :::
@@ -56,6 +59,7 @@ Design Systems, Cobalt
56
59
  :::div{style.fontFamily="var(--font-heading)" style.fontWeight="700" style.fontSize="1.05rem"}
57
60
  Theo Marsh
58
61
  :::
62
+
59
63
  :::div{style.fontSize="0.9rem" style.color="var(--color-text-muted)"}
60
64
  Founder, Driftwork
61
65
  :::
@@ -65,6 +69,7 @@ Founder, Driftwork
65
69
  :::div{style.fontFamily="var(--font-heading)" style.fontWeight="700" style.fontSize="1.05rem"}
66
70
  Ravi Menon
67
71
  :::
72
+
68
73
  :::div{style.fontSize="0.9rem" style.color="var(--color-text-muted)"}
69
74
  Performance, Fathom
70
75
  :::
@@ -74,6 +79,7 @@ Performance, Fathom
74
79
  :::div{style.fontFamily="var(--font-heading)" style.fontWeight="700" style.fontSize="1.05rem"}
75
80
  Grace Liu
76
81
  :::
82
+
77
83
  :::div{style.fontSize="0.9rem" style.color="var(--color-text-muted)"}
78
84
  Accessibility Lead, Everly
79
85
  :::
@@ -83,6 +89,7 @@ Accessibility Lead, Everly
83
89
  :::div{style.fontFamily="var(--font-heading)" style.fontWeight="700" style.fontSize="1.05rem"}
84
90
  Owen Frost
85
91
  :::
92
+
86
93
  :::div{style.fontSize="0.9rem" style.color="var(--color-text-muted)"}
87
94
  Eng Manager, Beacon
88
95
  :::
@@ -92,6 +99,7 @@ Eng Manager, Beacon
92
99
  :::div{style.fontFamily="var(--font-heading)" style.fontWeight="700" style.fontSize="1.05rem"}
93
100
  Mira Patel
94
101
  :::
102
+
95
103
  :::div{style.fontSize="0.9rem" style.color="var(--color-text-muted)"}
96
104
  Creative Director, Halcyon
97
105
  :::