@jxsuite/starters 1.6.5 → 1.8.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.
Files changed (41) hide show
  1. package/README.md +32 -124
  2. package/package.json +4 -4
  3. package/sites/blog/document.schema.json +5052 -14
  4. package/sites/blog/package.json +3 -3
  5. package/sites/blog/project.schema.json +24 -3
  6. package/sites/course/document.schema.json +5052 -14
  7. package/sites/course/package.json +3 -3
  8. package/sites/course/project.schema.json +24 -3
  9. package/sites/event/document.schema.json +5052 -14
  10. package/sites/event/package.json +3 -3
  11. package/sites/event/project.schema.json +24 -3
  12. package/sites/fitness-studio/document.schema.json +5052 -14
  13. package/sites/fitness-studio/package.json +3 -3
  14. package/sites/fitness-studio/project.schema.json +24 -3
  15. package/sites/home-services/document.schema.json +5052 -14
  16. package/sites/home-services/package.json +3 -3
  17. package/sites/home-services/project.schema.json +24 -3
  18. package/sites/museum/document.schema.json +5052 -14
  19. package/sites/museum/package.json +3 -3
  20. package/sites/museum/project.schema.json +24 -3
  21. package/sites/nonprofit/document.schema.json +5052 -14
  22. package/sites/nonprofit/package.json +3 -3
  23. package/sites/nonprofit/project.schema.json +24 -3
  24. package/sites/portfolio/document.schema.json +5052 -14
  25. package/sites/portfolio/package.json +3 -3
  26. package/sites/portfolio/project.schema.json +24 -3
  27. package/sites/professional-firm/document.schema.json +5052 -14
  28. package/sites/professional-firm/package.json +3 -3
  29. package/sites/professional-firm/project.schema.json +24 -3
  30. package/sites/real-estate/document.schema.json +5052 -14
  31. package/sites/real-estate/package.json +3 -3
  32. package/sites/real-estate/project.schema.json +24 -3
  33. package/sites/restaurant/document.schema.json +5052 -14
  34. package/sites/restaurant/package.json +3 -3
  35. package/sites/restaurant/project.schema.json +24 -3
  36. package/sites/saas/document.schema.json +5052 -14
  37. package/sites/saas/package.json +3 -3
  38. package/sites/saas/project.schema.json +24 -3
  39. package/sites/shop/document.schema.json +5052 -14
  40. package/sites/shop/package.json +3 -3
  41. package/sites/shop/project.schema.json +24 -3
package/README.md CHANGED
@@ -1,14 +1,8 @@
1
1
  # @jxsuite/starters
2
2
 
3
- The catalogue of ready-made **starter sites** a user can clone when creating a
4
- new Jx project, either from Studio's New Project picker or with
5
- `bun create @jxsuite <directory> --template <id>`. The package is two things:
6
- `registry.json`, the picker metadata, and `sites/`, one complete buildable Jx
7
- project tree per starter.
3
+ The catalogue of ready-made **starter sites** a user can clone when creating a new Jx project, either from Studio's New Project picker or with `bun create @jxsuite <directory> --template <id>`. The package is two things: `registry.json`, the picker metadata, and `sites/`, one complete buildable Jx project tree per starter.
8
4
 
9
- The TypeScript module itself is metadata-only. It reads the registry and
10
- resolves a starter's directory; the copy-and-rewrite of a clone happens in
11
- [`@jxsuite/create`](../create/README.md)'s `generate.ts`.
5
+ The TypeScript module itself is metadata-only. It reads the registry and resolves a starter's directory; the copy-and-rewrite of a clone happens in [`@jxsuite/create`](../create/README.md)'s `generate.ts`.
12
6
 
13
7
  ## API
14
8
 
@@ -20,18 +14,11 @@ getStarter("restaurant"); // StarterMeta | undefined
20
14
  getStarterDir("restaurant"); // <SITES_DIR>/restaurant; throws on an unknown id
21
15
  ```
22
16
 
23
- `SITES_DIR` is `join(import.meta.dirname, "sites")`, so the same code resolves
24
- from the monorepo and from the copy staged inside the packaged desktop app.
25
- `getStarterDir` throws `Unknown starter: "<id>"` rather than handing back a path
26
- that does not exist. The registry is also exported raw as
27
- `@jxsuite/starters/registry.json`, for consumers that want the array without the
28
- module. The package publishes raw TypeScript: `exports["."]` is `./index.ts`,
29
- there is no build step, and the module imports only `node:fs` and `node:path`.
17
+ `SITES_DIR` is `join(import.meta.dirname, "sites")`, so the same code resolves from the monorepo and from the copy staged inside the packaged desktop app. `getStarterDir` throws `Unknown starter: "<id>"` rather than handing back a path that does not exist. The registry is also exported raw as `@jxsuite/starters/registry.json`, for consumers that want the array without the module. The package publishes raw TypeScript: `exports["."]` is `./index.ts`, there is no build step, and the module imports only `node:fs` and `node:path`.
30
18
 
31
19
  ## The registry contract
32
20
 
33
- `registry.json` is a flat JSON array. Every entry carries all eight fields;
34
- there are no optional keys and no defaults (`index.ts`, `StarterMeta`):
21
+ `registry.json` is a flat JSON array. Every entry carries all eight fields; there are no optional keys and no defaults (`index.ts`, `StarterMeta`):
35
22
 
36
23
  | Field | Contract |
37
24
  | ------------- | ------------------------------------------------------------ |
@@ -44,24 +31,13 @@ there are no optional keys and no defaults (`index.ts`, `StarterMeta`):
44
31
  | `accent` | Hex colour, `/^#[0-9a-fA-F]{3,8}$/` |
45
32
  | `thumbnail` | `data:image/…` URI (**generated**, see below) |
46
33
 
47
- `tests/registry.test.ts` asserts each of those, that ids are unique, and that
48
- every id maps to a `sites/<id>/project.json`. Never restate the number of
49
- starters in prose: `scripts/docs/check-site-claims.ts` reads `registry.json` and
50
- fails the root `README.md` or any `sites/jxsuite.com/pages/**` page claiming a
51
- different count (digits and number words alike). The same gate holds the
52
- templates page's `::starter-card` slugs to the registry ids, both directions, so
53
- a starter added without a card is caught too. It does not scan this file, so
54
- here the habit is the only guard.
34
+ `tests/registry.test.ts` asserts each of those, that ids are unique, and that every id maps to a `sites/<id>/project.json`. Never restate the number of starters in prose: `scripts/docs/check-site-claims.ts` reads `registry.json` and fails the root `README.md` or any `sites/jxsuite.com/pages/**` page claiming a different count (digits and number words alike). The same gate holds the templates page's `::starter-card` slugs to the registry ids, both directions, so a starter added without a card is caught too. It does not scan this file, so here the habit is the only guard.
55
35
 
56
- The registry is the source several unrelated gates read by path: the docs
57
- generator, the marketing-claims count check, the packaged-desktop bundle
58
- verifier, and the screenshot lane's shot selector.
36
+ The registry is the source several unrelated gates read by path: the docs generator, the marketing-claims count check, the packaged-desktop bundle verifier, and the screenshot lane's shot selector.
59
37
 
60
38
  ## Layout of `sites/`
61
39
 
62
- Each `sites/<id>/` is a complete, buildable Jx project. It contains
63
- `components/`, `layouts/`, `pages/`, `content/`, `public/`, `project.json`, a
64
- `package.json`, and two **committed generated** entry schemas:
40
+ Each `sites/<id>/` is a complete, buildable Jx project. It contains `components/`, `layouts/`, `pages/`, `content/`, `public/`, `project.json`, a `package.json`, and two **committed generated** entry schemas:
65
41
 
66
42
  ```
67
43
  sites/restaurant/
@@ -74,123 +50,55 @@ sites/restaurant/
74
50
  .gitignore # .cache, dist, node_modules
75
51
  ```
76
52
 
77
- `tests/validate.test.ts` holds the tree to its schemas: the two committed
78
- bundles must be self-contained (no relative `$ref`s survive), `project.json`
79
- must satisfy both `parseProjectConfig` and its own `project.schema.json`, every
80
- `{components,layouts,pages}/**/*.json` must validate against
81
- `document.schema.json` (and at least one must exist), and every
82
- `content/**/*.md` must start with frontmatter. `tests/validate-projects.test.ts`
83
- runs each starter through `@jxsuite/schema`'s `validateProjectFile` as well.
53
+ `tests/validate.test.ts` holds the tree to its schemas: the two committed bundles must be self-contained (no relative `$ref`s survive), `project.json` must satisfy both `parseProjectConfig` and its own `project.schema.json`, every `{components,layouts,pages}/**/*.json` must validate against `document.schema.json` (and at least one must exist), and every `content/**/*.md` must start with frontmatter. `tests/validate-projects.test.ts` runs each starter through `@jxsuite/schema`'s `validateProjectFile` as well.
84
54
 
85
- Starters are not uniform by design: the museum starter is the multilingual one
86
- (`i18n.locales: ["en", "fr-CA", "ar"]` with `routing: "prefix-except-default"`),
87
- and real-estate's `listings` collection uses `format: "Csv"` where the others
88
- use Markdown.
55
+ Starters are not uniform by design: the museum starter is the multilingual one (`i18n.locales: ["en", "fr-CA", "ar"]` with `routing: "prefix-except-default"`), and real-estate's `listings` collection uses `format: "Csv"` where the others use Markdown.
89
56
 
90
57
  ## Consumption: cloned, never depended on
91
58
 
92
- Nothing a user ships depends on this package. `@jxsuite/create` imports
93
- `getStarterDir` lazily (so blank projects never load the large starters
94
- package), copies the tree, and then re-stamps identity:
59
+ Nothing a user ships depends on this package. `@jxsuite/create` imports `getStarterDir` lazily (so blank projects never load the large starters package), copies the tree, and then re-stamps identity:
95
60
 
96
61
  ```sh
97
62
  bun create @jxsuite my-site --template restaurant
98
63
  ```
99
64
 
100
- - **Excluded from the copy**: `node_modules`, `dist`, `.cache`, `.jx-cache`,
101
- `.git`, and `images.json` (`packages/create/generate.ts`).
102
- - **`project.json` is preserved**, with only `name` / `url` / `description` /
103
- `build.adapter` re-stamped (plus design tokens when the quickstart supplies
104
- them). Content, components, layouts and public assets are copied verbatim.
105
- - **`package.json` is rebuilt from scratch** with current dependency ranges, so
106
- a clone never inherits whatever the in-repo starter pinned.
107
- - `--template` resolves built-in template ids first, then registry starter ids;
108
- an unknown id falls back to `blank`.
109
-
110
- Two other consumers read the registry live: the dev server exposes it to
111
- Studio's picker at `GET /__studio/starters`, returning `listStarters()` verbatim
112
- (specs/server.md §4.1), and the desktop app imports `listStarters` directly in
113
- both its Electrobun and Chromium window layers.
65
+ - **Excluded from the copy**: `node_modules`, `dist`, `.cache`, `.jx-cache`, `.git`, and `images.json` (`packages/create/generate.ts`).
66
+ - **`project.json` is preserved**, with only `name` / `url` / `description` / `build.adapter` re-stamped (plus design tokens when the quickstart supplies them). Content, components, layouts and public assets are copied verbatim.
67
+ - **`package.json` is rebuilt from scratch** with current dependency ranges, so a clone never inherits whatever the in-repo starter pinned.
68
+ - `--template` resolves built-in template ids first, then registry starter ids; an unknown id falls back to `blank`.
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.
114
71
 
115
72
  ## Authoring or modifying a starter
116
73
 
117
74
  1. Add the `sites/<id>/` tree and a `registry.json` entry with all eight fields.
118
- 2. `bun run schema:generate-all` regenerates every `project.schema.json` and
119
- `document.schema.json`. **Always via this script**, never by hand: it runs
120
- `schema:clean-roots` first (see below). `bun run schema:verify` proves the
121
- result in CI, so a stale entry schema is a red build.
122
- `.github/workflows/schemas.yml` also regenerates it and pushes the fix to
123
- your branch, with a comment naming the JSON Pointers that moved.
124
- 3. `bun run docs:generate`, because `docs/studio/projects/starters.md` is
125
- rendered from `registry.json` by `scripts/docs/generators/starters.ts`.
126
- Hand-editing it is a bug; CI diffs the page.
127
- 4. `bun run screenshots:thumbnails`. The `thumbnail` data URI is not
128
- hand-authored. The script builds the starter with image optimization off,
129
- serves `dist/`, screenshots the hero viewport in headless Chromium, and
130
- writes the small JPEG into `registry.json` plus a full-res JPEG into
131
- `sites/jxsuite.com/public/starters/<id>.jpg`. (This is why `registry.json` is
132
- large.)
75
+ 2. `bun run schema:generate-all` regenerates every `project.schema.json` and `document.schema.json`. **Always via this script**, never by hand: it runs `schema:clean-roots` first (see below). `bun run schema:verify` proves the result in CI, so a stale entry schema is a red build. `.github/workflows/schemas.yml` also regenerates it and pushes the fix to your branch, with a comment naming the JSON Pointers that moved.
76
+ 3. Nothing for the docs: `docs/studio/projects/starters.md` is rendered from `registry.json` by `scripts/docs/generators/starters.ts` when the site builds, and is never committed (`bun run docs:generate` previews it).
77
+ 4. `bun run screenshots:thumbnails`. The `thumbnail` data URI is not hand-authored. The script builds the starter with image optimization off, serves `dist/`, screenshots the hero viewport in headless Chromium, and writes the small JPEG into `registry.json` plus a full-res JPEG into `sites/jxsuite.com/public/starters/<id>.jpg`. (This is why `registry.json` is large.)
133
78
  5. Photos, if the starter ships any:
134
79
 
135
80
  ```sh
136
81
  PEXELS_API_KEY=… bun packages/starters/scripts/fetch-photos.ts <site-id> [--force]
137
82
  ```
138
83
 
139
- `images.json` holds `{ site, thumbnail?, images }`, where each image is
140
- `{ role, query, orientation?, photoId? }`. The pinned `photoId` makes re-runs
141
- fetch the _same_ images; `--force` re-picks even pinned ones. The script
142
- upserts a per-site block in `CREDITS.md` between `<!-- site:<id>:start -->`
143
- and `<!-- site:<id>:end -->`.
144
- Committed output is plain image files, so scaffolded projects have no Pexels
145
- or network dependency.
84
+ `images.json` holds `{ site, thumbnail?, images }`, where each image is `{ role, query, orientation?, photoId? }`. The pinned `photoId` makes re-runs fetch the _same_ images; `--force` re-picks even pinned ones. The script upserts a per-site block in `CREDITS.md` between `<!-- site:<id>:start -->` and `<!-- site:<id>:end -->`. Committed output is plain image files, so scaffolded projects have no Pexels or network dependency.
146
85
 
147
- 6. `bun test --isolate` from `packages/starters`. Per-file coverage is gated at
148
- 99% lines / 99% functions (`bunfig.toml`); `sites/`, `scripts/` and `tests/`
149
- are excluded from coverage.
86
+ 6. `bun test --isolate` from `packages/starters`. Per-file coverage is gated at 99% lines / 99% functions (`bunfig.toml`); `sites/`, `scripts/` and `tests/` are excluded from coverage.
150
87
 
151
- Adding a starter needs **no** desktop config change:
152
- `packages/desktop/scripts/verify-bundle.ts` derives its checklist from the
153
- staged registry, so every new id is covered automatically.
88
+ Adding a starter needs **no** desktop config change: `packages/desktop/scripts/verify-bundle.ts` derives its checklist from the staged registry, so every new id is covered automatically.
154
89
 
155
90
  ## Hazards
156
91
 
157
- **The shadowed core.** A starter's `package.json` pins _published_ `@jxsuite/*`
158
- ranges. It must, because it is a template a user scaffolds from, and starters
159
- are not bun workspace members, so `workspace:^` is unavailable. Iterating a
160
- starter in Studio runs `bun install` in that root, which materialises a real
161
- `@jxsuite/schema` beside a workspace far ahead of it. That has already produced
162
- a starter document schema narrower than the starter's own content, unnoticed for
163
- six weeks (`scripts/check-shadowed-core.ts` carries the full post-mortem).
164
- `bun run schema:generate-all` therefore runs `schema:clean-roots`
165
- (`bun scripts/check-shadowed-core.ts --fix`) first, removing only
166
- `node_modules/@jxsuite/*` and a stray lockfile. Third-party dependencies stay,
167
- because the install is what makes the starter preview, and a workspace
168
- _symlink_ is never removed.
169
-
170
- **Never put that cleanup in a starter's `package.json`.** This package publishes
171
- `sites/`, so those manifests ship to end users; a `postinstall` or `preschema`
172
- hook there would run on their machine and delete the dependencies they just
173
- installed. The monorepo has the workspace being shadowed, so the monorepo owns
174
- the cleanup.
175
-
176
- **Do not hand-edit the `@jxsuite/*` ranges in `sites/*/package.json`.**
177
- release-please rewrites them inside its release commit via `extra-files`; the
178
- gate is `bun run templates:check` (`templates:sync` to repair).
179
-
180
- **Packaged-desktop path contract.** ElectroBun inlines the bun-side JS graph, so
181
- `import.meta.dirname` resolves to `app/bun/` at runtime. `registry.json` and
182
- `sites/` must therefore be staged to `bun/registry.json` and `bun/sites` by
183
- `build.copy` in `packages/desktop/electrobun.config.ts` (specs/desktop.md §7.4).
184
-
185
- **The screenshot lane ignores this package's source.** It watches only
186
- `registry.json` and the six starter roots a shot actually opens
187
- (`.github/workflows/screenshots.yml`); a registry change arms exactly one shot,
188
- `new-project`, because that modal's gallery _is_ `listStarters()`.
92
+ **The shadowed core.** A starter's `package.json` pins _published_ `@jxsuite/*` ranges. It must, because it is a template a user scaffolds from, and starters are not bun workspace members, so `workspace:^` is unavailable. Iterating a starter in Studio runs `bun install` in that root, which materialises a real `@jxsuite/schema` beside a workspace far ahead of it. That has already produced a starter document schema narrower than the starter's own content, unnoticed for six weeks (`scripts/check-shadowed-core.ts` carries the full post-mortem). `bun run schema:generate-all` therefore runs `schema:clean-roots` (`bun scripts/check-shadowed-core.ts --fix`) first, removing only `node_modules/@jxsuite/*` and a stray lockfile. Third-party dependencies stay, because the install is what makes the starter preview, and a workspace _symlink_ is never removed.
93
+
94
+ **Never put that cleanup in a starter's `package.json`.** This package publishes `sites/`, so those manifests ship to end users; a `postinstall` or `preschema` hook there would run on their machine and delete the dependencies they just installed. The monorepo has the workspace being shadowed, so the monorepo owns the cleanup.
95
+
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
+
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).
99
+
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()`.
189
101
 
190
102
  ## Versioning
191
103
 
192
- Published to npm as `@jxsuite/starters`. Like every `@jxsuite` package, it ships
193
- TypeScript source and follows the monorepo's release train (the `starters`
194
- release-please component). Within the monorepo, `@jxsuite/create` depends on it
195
- via `workspace:^`. Because consumption is a one-time clone, publishing a new
196
- version never changes an existing project.
104
+ Published to npm as `@jxsuite/starters`. Like every `@jxsuite` package, it ships TypeScript source and follows the monorepo's release train (the `starters` release-please component). Within the monorepo, `@jxsuite/create` depends on it via `workspace:^`. Because consumption is a one-time clone, publishing a new version never changes an existing project.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jxsuite/starters",
3
- "version": "1.6.5",
3
+ "version": "1.8.0",
4
4
  "description": "Starter site templates for new Jx projects",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -26,9 +26,9 @@
26
26
  "test:coverage": "bun test --isolate --coverage"
27
27
  },
28
28
  "devDependencies": {
29
- "@jxsuite/parser": "^1.6.0",
30
- "@jxsuite/runtime": "^3.0.0",
31
- "@jxsuite/schema": "^2.0.0",
29
+ "@jxsuite/parser": "^1.8.0",
30
+ "@jxsuite/runtime": "^4.0.0",
31
+ "@jxsuite/schema": "^2.2.0",
32
32
  "ajv": "^8.20.0",
33
33
  "ajv-formats": "^3.0.1"
34
34
  }